Utilizing Graphql Interfaces with MongoDB

Currently, I am exploring the realm of constructing a GraphQL API using MongoDB and I am focusing on grasping the concept of interfaces.

I have a decent understanding of it and have gone through several videos, talks, and how-to guides, but I am stuck on one thing - how to set up the query resolver.

The format that keeps coming up is: groups: () => { ... }

In this case, groups would be part of the query type and therefore requires the MongoDB query.

This brings me to the main question:

What exactly should go inside the {...} ?

    Query: {
        groups: () => { ... },
        families: () => Family.find(),
        members: () => Member.find(),
    },

My dilemma with the query lies in figuring out: "How do we form the query for groups since it's not a MongoDB document?"

ADDITIONAL DETAILS:

Here is the complete type definition:

export const typeDefs = gql`

    interface Group {
        id: ID!
        name: String!
    }

    type Family implements Group {
        id: ID!
        name: String! # persons family name
        numberOfPeople: Int
    }

    type Member implements Group {
        id: ID!
        name: String! # persons first name
        age: Int!
    }

    type Query {
        groups: [Group]
        families: [Family]
        members: [Member]
    }
}

And here is the resolver:

export const resolvers = {

    Group: {
        __resolveType(group, context, info){
          if(group.family){
            return 'Family';
          }
    
          if(group.member){
            return 'Member';
          }
    
          return null;
        },
      },

    Query: {
        groups: () => { ... },
        families: () => Family.find(),
        members: () => Member.find(),
    }
}

The goal is to have Family and Member as separate documents containing data while utilizing Group as the interface to create a unified query.

Answer №1

Upon re-reading your post, it seems that the element you are trying to access may not exist as expected. At the __resolveType stage, validation is being performed against a schema property.

// Group:
     {
        __resolveType(group, context, info){
          if(group.family){ // The property 'family' is not defined in a group implementation.
            return 'Family';
          }
    
          if(group.member){
            return 'Member';
          }
    
          return null;
        },
      },

To ensure proper validation, consider checking against a specified unique property from either the Family or Member implementation like so:

// Group:
     {
        __resolveType(group, context, info){
          if(group.numberOfPeople){
            return 'Family';
          }
    
          if(group.age){
            return 'Member';
          }
    
          return null;
        },
      },

When querying groups:

`
{
  groups {
    id
    name
    ... on Family {
      numberOfPeople 
    }
    ... on Member {
      age
    }
  }
}
`

Refer to Apollo Docs for more information


Retrieve Automatically Generated Interfaces and Typings.

If you are looking to automatically generate interfaces and typings for TypeScript from your schema, consider using graphql-code-generator. This tool also offers a plugin to generate mongoDB models automatically.

For quick results, paste your schema in the provided field here.


Quick Setup for TypeScript:

  1. Install

npm i -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-resolvers

This command will install the CLI, typescript, and typescript-resolvers plugins.

  1. Create a codegen.yml file in your root directory with the following content:
overwrite: true
schema: 'http://localhost:3500/graphql'
generates:
  src/utils/codegen/graphql.ts:
    plugins:
      - 'typescript'
      - 'typescript-resolvers'
  1. Run the following command:

graphql-codegen --config codegen.yml --watch src/**/*.ts

  1. Implement the generated typings in your project:
// Import the types from your generated TS file.
import { MutationResolvers, QueryResolvers, Resolvers } from '@/utils/codegen/graphql'

const Query: QueryResolvers = {
  players: () => players
}

const Mutation: MutationResolvers = {
  updatePlayer: () => player
}

const resolvers: Resolvers = {
  Query,
  Mutation
};
export default resolvers;

Examples of screenshoots:

Intellisense and Autocomplete

Proper Validation

Answer №2

Just wanted to share some helpful information for those seeking it - this is the snippet that I inserted into the Query{ ... }

Essentially, this code represents the function responsible for executing database queries.

Groups should be used for plural results, while Group is appropriate for singular results.

groups: async () => {

    let models = mongoose.modelNames()

    let results = []

    for(let model of models) {
        let tempResult = await mongoose.model(model).find()
        results.push(tempResult)
    }

    let flattenedResults = results.flat()

    return flattenedResults

},

group: (_, { id }) => {
    
    return mongoose.modelNames().map(async modelName => {

        if (await mongoose.model(modelName).exists({"_id": ObjectID(id)})) {
            return mongoose.model(modelName).findOne({"_id": ObjectID(id)})
        } 

    })

},

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The Sequelize-powered Express API endpoint consistently fails to provide any data upon request

I am currently working on an app built with Express and Sequelize as the ORM. The models I have set up are functioning properly, but I need to incorporate information from another model to generate a filtered list. The purpose of the controller for this pa ...

Tips on arranging paths for a Node.js application with subcategories and structuring them in a modular way

I have some knowledge of Node.js and I'm experimenting with creating my own application. While I have a good understanding of how routes and controllers function, I am finding tutorials that only show routes with similar structures which are too basic ...

Obtain an assortment and append a new element to the output

I am trying to create a function in the Server script that can return a collection along with an additional value. For example: Meteor.publish("users", function () { var users; users = Meteor.users.find(); users.forEach(function (user){ ...

Encountering NodeJs Error 401(Unauthorized) while implementing passport-jwt in my project

I am currently developing an authentication application using Node.js, MongoDB, and the Passport-JWT middleware. I have successfully implemented the login functionality and I am able to obtain a token. However, when trying to access the user profile after ...

Ways to ensure the synchronous execution of asynchronously invoked functions

I'm currently navigating the world of asynchronous code and trying to grasp its workings. As I construct a Node Express application that interfaces with a database, my aim is for it to interact with a Sqlite database in a development setting. (The pr ...

Updating the MongoDB database name in a testing environment using NodeJS

Currently, I am utilizing the following code snippet to establish a connection with MongoDB: MongoClient.connect( process.env.MONGO_HOST, { useUnifiedTopology: true }, function (err, client) { _db = client.db(process.env.DB_NAME); ...

Setting up PhalconPHP and Node.js configurations

Is there a way to merge configurations for PHP and JavaScript, considering they both interact with the same database? How can these be organized cleanly? Additionally, what file structure would be best for an application utilizing PhalconPHP and Express. ...

Utilizing Node.js, Express, and OpenID Connect for seamless authentication redirection to the home page

Successfully integrated Passport OpenId Connect (https://github.com/jaredhanson/passport-openidconnect) into my application. passport.use('provider', new OICStrategy({ issuer: "https://fssfed.stage.ge.com/fss", authorizationURL : "https://M ...

Encountering a problem with the node.js version while trying to install

Currently in the process of setting up my Raspberry Pi as a node.js server. Recently performed a clean installation of Raspberian Subsequently, I installed node Upon running node -v, the system displays: v0.10.25 Proceeded to install npm When checking ...

Error in Browserify Express App: Unexpected token while parsing the file

I have been attempting to browserify a javascript file. When I run the command: browserify global.js -o bundle.js An error message is returned: Error: Parsing file C:\ocquiz\public\javascripts\global.js: Unexpected token (756 ...

Issue with accessing cookies set with 'http: true' on an Express server when using Nextjs and a custom server configuration

In the process of handling cookies on my custom Express server with the property httpOnly: true, I've encountered an issue while trying to fetch the cookie in my NextJs app's server side method getServerSideProps. Despite being able to access the ...

Enhance your website with multiple interactive elements by incorporating several flashes through ExpressJS

When using request.flash to send flash messages to users, I encountered an issue. It seems that request.flash does not allow me to send multiple flash messages to a view at once. This is the code I tried: request.flash('danger', 'some flas ...

What could be causing the lack of data for the current user?

I have been attempting to fetch the current user session and display the data in the view, but nothing is appearing. I even checked the database and confirmed an active session with all the necessary information. I attempted logging the user out and starti ...

Error Uploading File - Functioning in Postman but not on website interface

I'm currently pursuing the full stack certification on devchallenges.io and tackling the authentication app challenge. So far, I've successfully implemented the login and register functionality, as well as fetching the logged-in user's infor ...

The Postman software seems to be experiencing some difficulty with a "GET" request, as it is producing an error message stating "Failed to retrieve response Error: read ECONNRESET" while utilizing Node JS with PostgreSQL as the backend

Recently, I delved into the world of login authentication using JWT Tokens by following a video tutorial. The journey involved creating a PostgreSQL database, integrating it with my Node JS server, and testing out registration and login commands. Surprisin ...

Guide to using Node.js to efficiently add documents to several collections in a single query

I am exploring the possibility of inserting documents into multiple collections with a single query. Let's say I have two collections named person and address. My goal is to insert documents into both collections using just one query. Specifically, d ...

Navigate to a different URL following a post request using AJAX and EXPRESS

Currently, I am diving into the world of node.js servers by creating a login website. Users can input their username, which is then sent via an ajax post request to the server and stored in an array of all users. My goal is to redirect users to a personali ...

What is the best way to search for a specific item in Express.js?

I recently got the Leaderboard API issue fixed, but now I'm encountering a new problem with express Querying. Specifically, I'm attempting to search for a specific Discord ID using quick.db as my database. I've included an excerpt of my expr ...

I am having trouble initializing npm due to an error

I am currently working on a Node.js project but I am having trouble starting Node.js. In my existing Angular project, and after creating a new project with the following commands: sudo npm install -g @angular/cli After that, run: ng new mean-angular5 ...

What is the term used for the objects that res.render passes?

I constantly find myself struggling with defining objects inside res.render. Is there a way to define them globally or outside of res.render? I hope someone can offer some guidance.. here is a sample code snippet: router.get("/home/blog", function(req,r ...