0

I made a GraphQL API to retrieve and manipulate data in a mongo database. This data represents an author that contains a list of books as shown in Author.ts.

Author.ts:

import { Document, Model, model, Schema } from "mongoose";
import { Ibook } from "./book";

export interface Iauthor extends Document {
    name: String;
    books: Array<Ibook>;
  }
  
const AuthorSchema: Schema = new Schema({
    name: { type: String, required: true },
    books: { type: Array, required: true }
  });
  
export const Author: Model<Iauthor> = model('author', AuthorSchema);

Book.ts:

import {Document, Model, model, Schema} from "mongoose";

export interface Ibook extends Document {
    title: String;
    pages: Number;
  }
  
const BookSchema: Schema = new Schema({
    title: { type: String, required: true },
    pages: { type: Number, required: true }
  });
  
export const Book: Model<Ibook> = model('book', BookSchema);

I'm using query resolvers and mutation resolvers to read and manipulate these objects. I just migrated to graphql-compose-mongoose to generate the resolvers instead of programming them myself. I succeeded in migrating every query and mutation till I encountered my resolver "AssignBooktoAuthor". This basicly is a resolver that adds a book object to the authors books list. I simply do not know how to get it working with graphql-compose-mongoose.

composer.ts:

import { composeMongoose } from "graphql-compose-mongoose";
import { schemaComposer } from "graphql-compose";
import { Book } from "./models/book";
import { Author } from "./models/author";

const customizationOptions = {};
const BookTC = composeMongoose(Book, customizationOptions);
const AuthorTC = composeMongoose(Author, customizationOptions);

//in aparte file zetten prob
schemaComposer.Query.addFields({
  getAllBooks: BookTC.mongooseResolvers.findMany(),
  getBookById: BookTC.mongooseResolvers.findById(),
  getAllAuthors: AuthorTC.mongooseResolvers.findMany(),
  getAuthorById: AuthorTC.mongooseResolvers.findById(),
});

schemaComposer.Mutation.addFields({
  CreateBook: BookTC.mongooseResolvers.createOne(),
  UpdateBook: BookTC.mongooseResolvers.updateById(),
  DeleteBook: BookTC.mongooseResolvers.removeById(),
  CreateAuthor: AuthorTC.mongooseResolvers.createOne(),
  UpdateAuthor: AuthorTC.mongooseResolvers.updateById(),
  DeleteAuthor: AuthorTC.mongooseResolvers.removeById(),
  /**AssignBooktoAuthor: AuthorTC.mongooseResolvers.///What function does this??///**/
});

const graphqlSchema = schemaComposer.buildSchema();
export default graphqlSchema;

gql.ts (server file):

import { ApolloServer, gql } from "apollo-server-express";
import * as mongoose from "mongoose";
import * as express from "Express";
import * as dotenv from "dotenv";
import * as jwt from "jsonwebtoken";
import graphqlSchema from "./composer";

const app = express();
 
dotenv.config();

(async () => {
  mongoose.connect("mongodb+srv://xxxxxxx:[email protected]/myFirstDatabase?retryWrites=true&w=majority", { useUnifiedTopology: true , useNewUrlParser: true});

  const server = new ApolloServer({ 
    schema: graphqlSchema,
  });

  await server.start();

  //verifying token 
  app.use((req, res, next) => {
    const Token = req.header('auth-token');
    try{
      (Token && jwt.verify(Token, process.env.TOKEN_SECRET)) ? next() : console.log("mw: Unauthorized");
    }catch(err){
      console.log("mw:Unauthorized");
    }
  });

  server.applyMiddleware({ app });
  
  app.listen({ port: 4000 }, () =>
  console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`)
  );

})();

Since the support on graphql-compose-mongoose is not that big I hope there is someone who can help me with this problem!

1 Answer 1

1

I found the solution myself!

Graphql supports the use of adding relations by object id. So in the model you have to assign a type called something like authorid and then add a "ref" with the objectid type. see book.ts for example. See composer.ts for the addrelation example.

Book.ts:

export interface Ibook extends Document {
  title: String;
  pages: Number;
  author: Schema.Types.ObjectId; 
}
  
const BookSchema: Schema = new Schema({
  title: { type: String, required: true },
  pages: { type: Number, required: true },
  author: { type: Schema.Types.ObjectId, ref:"author", required: true}
});

Composer.ts:

BookTC.addRelation('author', {
  resolver: () => AuthorTC.mongooseResolvers.findById(),
  prepareArgs:{
    _id: source => source.author,
    skip: null,
    sort: null,    
  },
  projection: {author: true},
})

AuthorTC.addRelation('books', {
  resolver: () => BookTC.mongooseResolvers.findMany(),
  prepareArgs: {
    filter: source => ({ author: source._id }),
  },
  projection: { id: true },
});

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.