graphql.GraphQLSchema: 使用什么类型的参数来抓取查询传递给 mongo db.collection.find 来解析查询
graphql.GraphQLSchema: what type of argument to use to grab the query to pass to mongo db.collection.find to resolve the query
我正在学习如何使用 express、express-graphql、**graphql、 开发 GraphQL 服务mongo塞,
db.collection.find 有一个可选的 query 参数,它使用查询运算符指定选择过滤器。
我想知道是否可以定义一个模式,在该模式中为查询字段定义一个参数,最终它按原样传递给集合查找方法。
例如我希望 graphql 查询:
{ todosQuerable(query: {title: "Andare a Novellara"})
{ _id, title, completed }
}
回复:
{
"data": {
"todos": [
{
"title": "Andare a Novellara",
"completed": false
}
]
}
}
自从 mongo
> db.Todo.find({title: 'Andare a Novellara'})
{ "_id" : ObjectId("600d95d2e506988bc4430bb7"), "title" : "Andare a Novellara", "completed" : false }
我在想:
todosQuerable: {
type: new graphql.GraphQLList(TodoType),
args: {
query: { type: <???????????????> },
},
resolve: (source, { query }) => {
return new Promise((resolve, reject) => {
TODO.find(query, (err, todos) => {
if (err) reject(err)
else resolve(todos)
})
})
}
}
我已经尝试了几次,但无法确定在这种情况下我应该使用哪种类型
谁帮忙重现问题here the source repository of my tests
请注意,这工作正常:
todosByTitle: {
type: new graphql.GraphQLList(TodoType),
args: {
title: { type: graphql.GraphQLString },
},
resolve: (source, { title }) => {
return new Promise((resolve, reject) => {
TODO.find({title: {$regex: '.*' + title + '.*', $options: 'i'}}, (err, todos) => {
if (err) reject(err)
else resolve(todos)
})
})
}
}
但我正在寻找的是更通用的东西:我想获取名为 query
的 graphql 字段参数并将其按原样传递给 query mongo 集合的参数 find。
所以好消息是你可以做任何你想做的事。坏消息是:
- 你必须自己做
- 您必须添加每个可搜索字段,因此您最终可能会在此处得到 Todo 对象的两个副本。
您要查找的类型只是一个自定义输入对象类型,如下所示:
请注意下面的 GraphQLInputObjectType
与 GraphQLObjectType
.
不同
var TodoQueryType = new graphql.GraphQLInputObjectType({
name: 'TodoQuery',
fields: function () {
return {
_id: {
type: graphql.GraphQLID
},
title: {
type: graphql.GraphQLString
},
completed: {
type: graphql.GraphQLBoolean
}
}
}
});
todosQuerable: {
...
type: new graphql.GraphQLList(TodoType),
...
args: {
query: { type: TodoQueryType },
},
...
}
这两个查询非常有用!
(这是我使用的别名,所以我可以在一次调用中进行两次相同的查询)
{
titleSearch: todosQuerable(query:{ title:"Buy orange" }) {
_id
title
completed
}
idSearch: todosQuerable(query:{ _id:"601c3f374b6dcc601890048d" }) {
_id
title
completed
}
}
脚注:
只是说,这通常是一个 GraphQL 反模式,因为这是根据您的数据库选择构建 API,而不是作为客户端驱动的 API。
按要求编辑正则表达式:
如果您尝试进行正则表达式查找,则必须弄清楚如何以编程方式将字符串转换为正则表达式。也就是说,您的输入是 string
("/Novellara/"
),但是 mongoose 需要传递 RegExp
才能使用通配符(/Novellara/
,无引号)。
您可以通过多种方式做到这一点,但我将展示一个示例。如果您将输入字段更改为使用值和 isExpression 的两个属性,如下所示,您可以这样做,但您必须专门设计您的查询,因为它不再只是一个传递。
var ExpressableStringInput = new graphql.GraphQLInputObjectType({
name: 'ExpressableString',
fields: {
value: {
type: graphql.GraphQLString
},
isExpression:{
type: graphql.GraphQLBoolean,
defaultValue: false,
}
}
})
var TodoQueryType = new graphql.GraphQLInputObjectType({
name: 'TodoQuery',
fields: function () {
return {
_id: {
type: graphql.GraphQLID
},
title: {
type: ExpressableStringInput
},
completed: {
type: graphql.GraphQLBoolean
}
}
}
});
// resolver
todosQuerable: {
type: new graphql.GraphQLList(TodoType),
args: {
query: { type: TodoQueryType },
},
resolve: async (source, { query }) => {
const dbQuery = {};
if (query.title.isExpression) {
dbQuery.title = new RegExp(query.title.value);
} else {
dbQuery.title = query.title.value;
}
return new Promise((resolve, reject) => {
TODO.find(dbQuery, (err, todos) => {
if (err) reject(err)
else resolve(todos)
})
})
}
}
您的查询将类似于
query {
todosQuerable(query:{ title: { value: "Buy.*", isExpression: true }}) {
_id
title
completed
}
}
这个查询在我看来很有意义。如果我考虑要向用户显示的表单,可能会有一个输入框和一个显示“这是正则表达式吗?”的复选框。或其他东西,这将填充此查询。
或者,您可以像字符串匹配一样进行操作:如果第一个和最后一个字符是“/”,您会在将其传递给 mongoose 之前自动将其转换为正则表达式。
我正在学习如何使用 express、express-graphql、**graphql、 开发 GraphQL 服务mongo塞,
db.collection.find 有一个可选的 query 参数,它使用查询运算符指定选择过滤器。
我想知道是否可以定义一个模式,在该模式中为查询字段定义一个参数,最终它按原样传递给集合查找方法。
例如我希望 graphql 查询:
{ todosQuerable(query: {title: "Andare a Novellara"})
{ _id, title, completed }
}
回复:
{
"data": {
"todos": [
{
"title": "Andare a Novellara",
"completed": false
}
]
}
}
自从 mongo
> db.Todo.find({title: 'Andare a Novellara'})
{ "_id" : ObjectId("600d95d2e506988bc4430bb7"), "title" : "Andare a Novellara", "completed" : false }
我在想:
todosQuerable: {
type: new graphql.GraphQLList(TodoType),
args: {
query: { type: <???????????????> },
},
resolve: (source, { query }) => {
return new Promise((resolve, reject) => {
TODO.find(query, (err, todos) => {
if (err) reject(err)
else resolve(todos)
})
})
}
}
我已经尝试了几次,但无法确定在这种情况下我应该使用哪种类型
谁帮忙重现问题here the source repository of my tests
请注意,这工作正常:
todosByTitle: {
type: new graphql.GraphQLList(TodoType),
args: {
title: { type: graphql.GraphQLString },
},
resolve: (source, { title }) => {
return new Promise((resolve, reject) => {
TODO.find({title: {$regex: '.*' + title + '.*', $options: 'i'}}, (err, todos) => {
if (err) reject(err)
else resolve(todos)
})
})
}
}
但我正在寻找的是更通用的东西:我想获取名为 query
的 graphql 字段参数并将其按原样传递给 query mongo 集合的参数 find。
所以好消息是你可以做任何你想做的事。坏消息是:
- 你必须自己做
- 您必须添加每个可搜索字段,因此您最终可能会在此处得到 Todo 对象的两个副本。
您要查找的类型只是一个自定义输入对象类型,如下所示:
请注意下面的 GraphQLInputObjectType
与 GraphQLObjectType
.
var TodoQueryType = new graphql.GraphQLInputObjectType({
name: 'TodoQuery',
fields: function () {
return {
_id: {
type: graphql.GraphQLID
},
title: {
type: graphql.GraphQLString
},
completed: {
type: graphql.GraphQLBoolean
}
}
}
});
todosQuerable: {
...
type: new graphql.GraphQLList(TodoType),
...
args: {
query: { type: TodoQueryType },
},
...
}
这两个查询非常有用!
(这是我使用的别名,所以我可以在一次调用中进行两次相同的查询)
{
titleSearch: todosQuerable(query:{ title:"Buy orange" }) {
_id
title
completed
}
idSearch: todosQuerable(query:{ _id:"601c3f374b6dcc601890048d" }) {
_id
title
completed
}
}
脚注:
只是说,这通常是一个 GraphQL 反模式,因为这是根据您的数据库选择构建 API,而不是作为客户端驱动的 API。
按要求编辑正则表达式:
如果您尝试进行正则表达式查找,则必须弄清楚如何以编程方式将字符串转换为正则表达式。也就是说,您的输入是 string
("/Novellara/"
),但是 mongoose 需要传递 RegExp
才能使用通配符(/Novellara/
,无引号)。
您可以通过多种方式做到这一点,但我将展示一个示例。如果您将输入字段更改为使用值和 isExpression 的两个属性,如下所示,您可以这样做,但您必须专门设计您的查询,因为它不再只是一个传递。
var ExpressableStringInput = new graphql.GraphQLInputObjectType({
name: 'ExpressableString',
fields: {
value: {
type: graphql.GraphQLString
},
isExpression:{
type: graphql.GraphQLBoolean,
defaultValue: false,
}
}
})
var TodoQueryType = new graphql.GraphQLInputObjectType({
name: 'TodoQuery',
fields: function () {
return {
_id: {
type: graphql.GraphQLID
},
title: {
type: ExpressableStringInput
},
completed: {
type: graphql.GraphQLBoolean
}
}
}
});
// resolver
todosQuerable: {
type: new graphql.GraphQLList(TodoType),
args: {
query: { type: TodoQueryType },
},
resolve: async (source, { query }) => {
const dbQuery = {};
if (query.title.isExpression) {
dbQuery.title = new RegExp(query.title.value);
} else {
dbQuery.title = query.title.value;
}
return new Promise((resolve, reject) => {
TODO.find(dbQuery, (err, todos) => {
if (err) reject(err)
else resolve(todos)
})
})
}
}
您的查询将类似于
query {
todosQuerable(query:{ title: { value: "Buy.*", isExpression: true }}) {
_id
title
completed
}
}
这个查询在我看来很有意义。如果我考虑要向用户显示的表单,可能会有一个输入框和一个显示“这是正则表达式吗?”的复选框。或其他东西,这将填充此查询。
或者,您可以像字符串匹配一样进行操作:如果第一个和最后一个字符是“/”,您会在将其传递给 mongoose 之前自动将其转换为正则表达式。