Giter Club home page Giter Club logo

graphql-mongoose-loader's Introduction

GraphQL Mongoose Loader CircleCI

Install

npm i @entria/graphql-mongoose-loader --save
yarn add @entria/graphql-mongoose-loader

Mongoose Dataloader Batch

Add batch to your GraphQL resolvers/loaders

Define a mongoose schema for your model

import mongoose from 'mongoose';

const Schema = new mongoose.Schema(
  {
    name: {
      type: String,
    },
    email: {
      type: String,
      required: true,
      index: true,
    },
    password: {
      type: String,
      hidden: true,
    },
  },
  {
    collection: 'User',
  },
);

export default mongoose.model('User', Schema);

Create a Dataloader for it

import { mongooseLoader } from '@entria/graphql-mongoose-loader';
import UserModel from './User';

export const getLoader = () => new DataLoader(ids => mongooseLoader(UserModel, ids));

Connection from Mongoose Cursor

Create a connection from mongoose cursor

import { connectionFromMongoCursor } from '@entria/graphql-mongoose-loader';

export const loadUsers = async (context: GraphQLContext, args: ConnectionArguments) => {
  const where = args.search
    ? {
        name: {
          $regex: new RegExp(`^${args.search}`, 'ig'),
        },
      }
    : {};
  const users = UserModel.find(where, { _id: 1 }).sort({
    createdAt: -1,
  });

  return connectionFromMongoCursor({
    cursor: users,
    context,
    args,
    loader: load,
  });
};

Connection from Mongoose Aggregate

Create a connection from mongoose aggregate

import { connectionFromMongoAggregate } from '@entria/graphql-mongoose-loader';

export const loadUsersThatHaveGroup = async (context: GraphQLContext, args: ConnectionArguments) => {
  const aggregate = GroupModel.aggregate([
    {
      $lookup: {
        from: 'User',
        localField: 'users',
        foreignField: '_id',
        as: 'users',
      },
    },
    {
      // remove empty groups
      $match: { users: { $exists: true, $ne: [] } },
    },
    {
      // promote each user to a new document
      $unwind: '$users',
    },
    {
      $sort: {
        _id: 1,
      },
    },
    {
      $replaceRoot: { newRoot: '$users' },
    },
  ]);

  return connectionFromMongoAggregate({
    aggregate,
    context,
    args,
    loader: load,
  });
};

graphql-mongoose-loader's People

Contributors

andreabeggiato avatar augustocalaca avatar davidrossjones avatar dependabot-preview[bot] avatar dependabot[bot] avatar fakenickels avatar fersilva16 avatar igormaineti avatar jcmais avatar jgcmarins avatar julioxavierr avatar kebou avatar lucasbesen avatar mauriciomutte avatar maxaggedon avatar oskojess avatar ronal2do avatar sibelius avatar socksrust avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graphql-mongoose-loader's Issues

TypeError: Cannot read property 'model' of undefined

When trying to use ConnectionFromMongoCursor I'm getting the error:

TypeError: Cannot read property 'model' of undefined ... graphql-mongoose-loader/lib/ConnectionFromMongoCursor.js:53:34

Or this line:

clonedCursor = cursor.model.find().merge(cursor);

I've tried debugging and believe it's to do with the getTotalCount call but since this is async wrapped in the regeneratorRuntime its proving difficult. Is this a problem for anyone else?

Thank you.

Issue of deleting existing or adding a new user

  1. Imagine a case where initially we fetched 20 users (sorted according to createdAt: -1). It got us the ids: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]

  2. rerun the app and fetch only 10 users initially. It will give us ids as expected: [1,2,3,4,5,6,7,8,9,10]

  3. Delete the user with id: 2 and Load more 10 users

  4. It will skip the user with id: 11 and fetch the users with ids: [12,13,14,15,16,17,18,19,20,21]

I have not tested the case with addition; i believe it may have similar effect in the opposite direction. Not sure.

Please add a changelog or release notes

I'm upgrading from 2 to 4 which assumes breaking changes yet I have to dig through commits to find out if this is true yet what they are. Apologies if there is actually a log somewhere but I cannot find one in releases nor the readme or changelog.md

peerDependencies

Currently package.json says :

  "peerDependencies": {
    "graphql": "^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0"
  },

but I don't see any code directly relying on the graphql package...
On the contrary, graphql-relay and mongoose are require-d but not mentioned as peerDependencies.

how to populate sub documents for a document

I have got Post Schema which contains Comment Ids through References

const PostSchema = new Schema({
  title: { type: String },
  details: { type: String },
  comments: [{
    type: Schema.Types.ObjectId,
    ref: DB_MODELS.COMMENT,
  }],
});

PostSchema.statics.getComments = function(postId) {
  return this.findById(postId)
    .populate('comments')
    .then(post => post.comments);
};

const Post = mongoose.model('post', PostSchema);
export default Post;

My GraphQL type for the same:

const GraphQLPost = new GraphQLObjectType({
  name: 'Post',
  fields: {
    id: globalIdField('Post'),
    _id: { type: GraphQLID },
    title: { type: GraphQLString },
    details: { type: GraphQLString },
    comments: {
      type: CommentConnection,
      args: {
        ...connectionArgs,
      },
      resolve: async (post, args) => {
        console.log('resolving comments inside GraphQLPost..', args);
        const comments = await Post.getComments(post._id);
        if (!comments) {
          return [];
        }
        return connectionFromArray(comments, args);
      },
    },
  },
  interfaces: () => [nodeInterface],
});

export default GraphQLPost;

How i can use this module to load subdocuments for a document i.e. comments for a Post?

There are obvious problems with my existing approach as it will fetch all the comments for a post. That's why i want to use this module to paginate + use DataLoader.

fix CI

#!/bin/bash -eo pipefail
yarn lint
yarn run v1.5.1
$ eslint src/**

/home/circleci/app/src/__tests__/ConnectionFromMongoCursor.spec.js
  119:9  error  'userB' is assigned a value but never used  no-unused-vars
  120:9  error  'userC' is assigned a value but never used  no-unused-vars
  121:9  error  'userD' is assigned a value but never used  no-unused-vars

โœ– 3 problems (3 errors, 0 warnings)

error An unexpected error occurred: "Command failed.
Exit code: 1
Command: sh
Arguments: -c eslint src/**
Directory: /home/circleci/app
Output:
".
info If you think this is a bug, please open a bug report with the information provided in "/home/circleci/app/yarn-error.log".
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Exited with code 1

fix husky warning

Warning: Setting commit-msg script in package.json > scripts will be deprecated
Please move it to husky.hooks in package.json, a .huskyrc file, or a husky.config.js file
Or run ./node_modules/.bin/husky-upgrade for automatic update

See https://github.com/typicode/husky for usage

Tests not running

Jest test not running. Does not show any errors. My OS is Ubuntu 19, I use node v12.6.0, yarn v1.17.3 and jest 23.5.0.

Below is the print of my terminal:

image

fix type error

after some upgrades we know have a lot of type errors to fix

Generalisation of loaded keys

Hey guys,

Currently the mongooseLoader works only with the _id field, however it would be really useful to load data based on other keys as well (e.g. loading users by username).

It would only require a key field parameter in the mongooseLoader function. A possible implementation could be the folowing:

export default async function mongooseLoader(
  model: Mongoose$Document,
  keys: ReadonlyArray<string>,
  lean: boolean = true,
  keyField: string = '_id'
) {
  const results = lean ? await model.find({ [keyField]: { $in: keys } }).lean() : await model.find({ [keyField]: { $in: keys } });

  return normalizeResults(keys, keyField, cacheKeyFn)(results);
}

The lean and keyField parameters could be moved to an options object, too.

Please share your thoughts on it!

graphql-mongodb-loader

I am using mongodb native driver. Would you mind creating graphql-mongodb-loader as well? Thanks!

babel polyfill

First of all, thanks for this package, you save me from a long boilerplate code.
BTW, I encounter a little problem using this package:

if you try to use this module without babel-polyfill package you encounter this error:
error: ReferenceError: regeneratorRuntime is not defined

For a workaround you need to npm install babel-polyfill and require('babel-polyfill') in your app entry point.

Bye

what is it solving?

If you could give some introduction to what actually it is solving would be great.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.