Coder Social home page Coder Social logo

b1f6c1c4 / graphql-advanced-projection Goto Github PK

View Code? Open in Web Editor NEW
46.0 6.0 5.0 2.41 MB

Fully customizable Mongoose/MongoDB projection generator.

Home Page: https://www.npmjs.com/package/graphql-advanced-projection

License: MIT License

JavaScript 100.00%
graphql mongodb mongoose projection javascript graphql-advanced-projection graphql-projection apollo apollo-server

graphql-advanced-projection's People

Contributors

b1f6c1c4 avatar dependabot[bot] avatar greenkeeper[bot] avatar mathieutu 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

graphql-advanced-projection's Issues

Version 10 of node.js has been released

Version 10 of Node.js (code name Dubnium) has been released! 🎊

To see what happens to your code in Node.js 10, Greenkeeper has created a branch with the following changes:

  • Added the new Node.js version to your .travis.yml

If you’re interested in upgrading this repo to Node.js 10, you can open a PR with these changes. Please note that this issue is just intended as a friendly reminder and the PR as a possible starting point for getting your code running on Node.js 10.

More information on this issue

Greenkeeper has checked the engines key in any package.json file, the .nvmrc file, and the .travis.yml file, if present.

  • engines was only updated if it defined a single version, not a range.
  • .nvmrc was updated to Node.js 10
  • .travis.yml was only changed if there was a root-level node_js that didn’t already include Node.js 10, such as node or lts/*. In this case, the new version was appended to the list. We didn’t touch job or matrix configurations because these tend to be quite specific and complex, and it’s difficult to infer what the intentions were.

For many simpler .travis.yml configurations, this PR should suffice as-is, but depending on what you’re doing it may require additional work or may not be applicable at all. We’re also aware that you may have good reasons to not update to Node.js 10, which is why this was sent as an issue and not a pull request. Feel free to delete it without comment, I’m a humble robot and won’t feel rejected 🤖


FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

[Proposal] Optimise queries with nested population.

Hi,
I've seen in https://itnext.io/graphql-mongoose-a-design-first-approach-d97b7f0c869 how you handle nested, and ref relations.

Actually your way has some problems:

  • Storing an array of children in a parent is quite an anti pattern:

  • Populate directly in nested resolvers:

    • You will have as many calls as many the nested resolver will be called, so for nested object, at least the number of parents. If you have nested of nested it can be really problematic (hundred of calls very quickly).
    • As you're returning directly the children, you don't need to populate at all, a where in is enough.
    • We have to write all the resolvers by hand.

Solution: (yeah because, it's a proposal, I'm not here just to complain 😛)

  • For the array of children, just put the parentId in child. No more growing array, no more need to populate. And in mongoose, you can define virtual with ref, and it will be exactly the same. See http://mongoosejs.com/docs/populate.html#populate-virtuals.
    But this one is for information and have no link with this package.

  • For the nested resolvers: we have a way to do it muuuch better in my opinion.
    Indeed, we can directly populate all the nested and subnested items directly in the first resolver, by writing the populate option with the help of projections !

I've made a bunch of functions to convert projections to a populate config object, and so I can query directly all the demanded item with:

async campaigns(root, args, ctx, info) {
    const projections = project(info);
    const population = populate(projections);

    return Campaign.find({}, projections).populate(population);
},

And with that it will make the minimum number of queries to fetch all the needed documents. Example:

Query:

{
  campaigns {
    id
    title
    questions {
      id
      message
      answers {
        id
        value
      }
    }
  }
}

Mongoose requests done:

campaigns.find({}, { fields: { id: 1, title: 1, 'questions.id': 1, 'questions.message': 1, 'questions.answers.id': 1, 'questions.answers.value': 1, questions: 1 } })
questions.find({ campaignId: { '$in': [ ObjectId("5b59b5c6a30e7b2b8d1ea74f"), ObjectId("5b59b719ad4dd22bbd62750b"), ObjectId("5b59b719ad4dd22bbdv2750b"), [length]: 3 ] } }, { fields: { id: 1, message: 1, answers: 1, campaignId: 1 } })
answers.find({ questionId: { '$in': [ ObjectId("5b5a439a935a0d32bc688f15"), ObjectId("5b5a439a935a0d32bc588f15", ObjectId("5b5a439a935a0d32bc698f15", [length]: 3 ] } }, { fields: { id: 1, value: 1, questionId: 1 } })

Here we have 3 levels asked, so 3 queries in any case.

With nested resolvers, we would have for this concrete case:
10 Campaigns: 1 query.
20 Questions by Campaign: 10 * 1 queries.
3 Answers by Questions: 10 * 20 * 1 queries.

About 200 queries, for only 3 levels. And it will grow with each document and each level added.

Are you interested by a PR with theses functions, and then write some documentation/update the article?

How to use with non-existing types that wrap the results?

Hallo,

it's a bit difficult to explain...I have a MongoDB collection called "tracking-infos" and a GQL query that returns them for pagination:

type Query {
    trackingInfos(query: TrackingInfoQuery!): PaginatedTrackingInfos!
}

type PaginatedTrackingInfos {             <= This is "artificial"
    data: [TrackingInfo!]!
    total: Int!
}

type TrackingInfo {                  <= This is stored in MongoDB
    _id: String!
    shippingNumber: String!
    symbol: String!
    ....
}

The query on the web client looks like this:

query GetTrackingInfosForOverview($query: TrackingInfoQuery!) {
    trackingInfos(query : $query) {
        data {
            shippingNumber
            // Some other, but not all so that we need a working projection to prevent querying unnecessary stuff
        }
        total
    }
}

My resolver for the trackingInfos-Query looks like this:

const { project, resolvers } = gqlProjection({
		TrackingInfo: {
			proj: {
				"shippingNumber": 1,
				"symbol": 1,
                                ...
			}
		}
	};

....

	async trackingInfos(obj, args, context, info) {
		const proj = project(info);
                const total= await this.trackingInfoModel.getTrackingInfosCount(args.query, proj);
		const data= await this.trackingInfoModel.findTrackingInfos(args.query, proj);
		return {
			total,
			data
		};
	}

This won't work though, because the AST in info is "based" on the PaginatedTrackingInfos-type and not on TrackingInfo. I am scratching my head, but can't find a solution how to fix this :-(

Could you tell me if this is possible at all and give me a hint how to do it?

Thanks

Populate array of items always empty array

Hello, thank you very much for the work so far, it's really appreciated. However - the documentation can be more explicit :( maybe I can contribute in the near future.

The issue I am experiencing is with the following virtual field:

Screenshot 2020-03-21 at 10 13 37 PM

This virtual field is an array (notice option justOne: false)

I am selecting in graphql the virtual field as following:
Screenshot 2020-03-21 at 10 13 28 PM

Now please notice the comparison of a working and non working example. The different is adding the projection.
What happens is:

  • projection specified -> always empty for virtual field array
  • projection not specified -> correct array field value

Implementation
Screenshot 2020-03-21 at 10 13 13 PM

Result

Screenshot 2020-03-21 at 10 12 58 PM

What about mutations?

Hi, I'm using your package and trying to do something cool for mutations too.
Could you provide some examples?

Here an example of nested items, where I want just to add a child and return the parent.

For now, I have:

async addQuestion(root, { campaignId, question }, ctx, info) {
    const campaign = await Campaign.findById(campaignId);
    const lenght = campaign.questions.push(question);
    
    return campaign.save();
}
mutation($campaignId: ID, $question: QuestionInput) {
  addQuestion(question: $question, campaignId: $campaignId) {
    id
    title
  }
}

which is pretty bad because I can't really select any field of the object, and load everything.

If I use the projection in the findById, questions is undefined.

And if I have a lot of questions in campaign, they will all be loaded (with their own children) for nothing.

Do you have any ideas/tips ?

Thanks!

Typescript request

Could you pls write a d.ts file for this module so that it can support for typescript?
I have tried to write one by myself but some variables' types are confusing.

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.