apollostack/graphql-server - how to get the fields requested in a query from resolver

余生长醉 提交于 2020-01-21 07:08:07

问题


I am trying to figure out a clean way to work with queries and mongdb projections so I don't have to retrieve excessive information from the database. So assuming I have:

// the query
type Query {
  getUserByEmail(email: String!): User
}

And I have a User with an email and a username, to keep things simple. If I send a query and I only want to retrieve the email, I can do the following:

query { getUserByEmail(email: "test@test.com") { email } }

But in the resolver, my DB query still retrieves both username and email, but only one of those is passed back by apollo server as the query result.

I only want the DB to retrieve what the query asks for:

// the resolver
getUserByEmail(root, args, context, info) {
  // check what fields the query requested
  // create a projection to only request those fields
  return db.collection('users').findOne({ email: args.email }, { /* projection */ });
}

Of course the problem is, getting information on what the client is requesting isn't so straightforward.

Assuming I pass in request as context - I considered using context.payload (hapi.js), which has the query string, and searching it through various .split()s, but that feels kind of dirty. As far as I can tell, info.fieldASTs[0].selectionSet.selections has the list of fields, and I could check for it's existence in there. I'm not sure how reliable this is. Especially when I start using more complex queries.

Is there a simpler way?

In case you don't use mongDB, a projection is an additional argument you pass in telling it explicitly what to retrieve:

// telling mongoDB to not retrieve _id
db.collection('users').findOne({ email: 'test@test.com' }, { _id: 0 })

As always, thanks to the amazing community.


回答1:


Sure you can. This is actually the same functionality that is implemented on join-monster package for SQL based db's. There's a talk by their creator: https://www.youtube.com/watch?v=Y7AdMIuXOgs

Take a look on their info analysing code to get you started - https://github.com/stems/join-monster/blob/master/src/queryASTToSqlAST.js#L6-L30

Would love to see a projection-monster package for us mongo users :)

UPDATE: There is a package that creates a projection object from info on npm: https://www.npmjs.com/package/graphql-mongodb-projection




回答2:


Use graphql-fields

Apollo server example

const rootSchema = [`

    type Person {
        id: String!
        name: String!
        email: String!
        picture: String!
        type: Int!
        status: Int!
        createdAt: Float
        updatedAt: Float
    }

    schema {
    query: Query
    mutation: Mutation
    }

`];

const rootResolvers = {


    Query: {

        users(root, args, context, info) {
            const topLevelFields = Object.keys(graphqlFields(info));
            return fetch(`/api/user?fields=${topLevelFields.join(',')}`);
        }
    }
};

const schema = [...rootSchema];
const resolvers = Object.assign({}, rootResolvers);

// Create schema
const executableSchema = makeExecutableSchema({
    typeDefs: schema,
    resolvers,
});


来源:https://stackoverflow.com/questions/40687045/apollostack-graphql-server-how-to-get-the-fields-requested-in-a-query-from-res

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!