使用mongoDB的graphQL - 是否可以通过查询实现灵活性?

时间:2018-02-19 18:23:52

标签: mongodb graphql graphql-js

我最近开始学习和使用graphQL,我发现一个常见的模式是让查询足够灵活,可以接受_idlastfirst等输入, take等等。

这是形成查询的正确方法,还是可以遵循任何设计模式或最佳实践?

例如,这里是一个可搜索且可限制的集合的解析器。

Query: {
clients: async (parent, args, context) => {
  return await mongoDb
    .getCollection(CLIENTS_COLLECTION)
    .aggregate([
      {
        $match: {
          name: {
            $regex: args.input.text ? new RegExp(args.input.text) : '',
            $options: 'i'
          }
        }
      },
      { $limit: args.input.take || LIMIT }
    ])
    .toArray();
}
}

我是否还应在同一查询中添加_id查找的输入?过滤和排序怎么样?是否有太灵活的事情?

1 个答案:

答案 0 :(得分:0)

你应该看看GraphQL-to-MongoDB, or how I learned to stop worrying and love generated query APIs。它讨论了一个中间件包,它利用GraphQL的类型生成GraphQL API,并将从客户端发送的请求解析为MongoDB查询。它具有大多数标准查询操作。通过这种方式,您可以享受软件包提供的所有灵活性,而无需为数据模型的任何更改自行实现。

免责声明:这是我的博文。

package为您的架构字段args生成GraphQL输入类型,并包装resolve函数以将它们解析为MongoDB查询。

给出一个简单,经典的GraphQLType声明:

const PersonType = new GraphQLObjectType({
    name: 'PersonType',
    fields: () => ({
        age: { type: GraphQLInt },
        name: {
            type: new GraphQLNonNull(new GraphQLObjectType({
                name: 'NameType',
                fields: () => ({
                    firstName: { type: GraphQLString },
                    lastName: { type: GraphQLString }
                })
            }))
        }
    })
}); 

对于最常见的用例,您将使用getMongoDbQueryResolvergetGraphQLQueryArgs在GraphQL架构中构建一个字段。包装器提供的filterprojectionoptions可以直接传递给find函数。

person: {
    type: new GraphQLList(PersonType),
    args: getGraphQLQueryArgs(PersonType),
    resolve: getMongoDbQueryResolver(PersonType,
        async (filter, projection, options, source, args, context) =>
            await mongoDb.getCollection('person')
                .find(filter, projection, options).toArray()
    )
}

您可以发送到此类字段的查询示例:

{
    person (
        filter: {
            age: { GT: 18 },
            name: { 
                firstName: { EQ: "John" } 
            }
        },
        sort: { age: DESC },
        pagination: { limit: 50 }
    ) {
        name { 
            lastName
        }
        age
    }
}

还有一个用于变异字段的包装器和参数类型生成器。