在一个请求中接受一组动态大小和常见标量类型的 GraphQL 突变
GraphQL mutation that accepts an array of dynamic size and common scalar types in one request
我需要能够在单个请求中创建一个用户并添加它最喜欢的电影(一个对象数组,引用电影集合和他对每部电影的个人评分)。
看起来像这样的东西(伪代码)
var exSchema = `
type Mutation {
addUser(
name: String!
favMovies: [{ movie: String! #ref to movies coll
personal_rating: Int! # this is different for every movie
}]
) : User
}
...
`
在单个请求中执行此操作的 graphql 方法是什么?我知道我可以用多个 mutations/requests 来达到结果,但我想用一个来完成。
将它们作为 JSON 字符串传递。我就是这么做的。
你可以像这样传递一个数组
var MovieSchema = `
type Movie {
name: String
}
input MovieInput {
name: String
}
mutation {
addMovies(movies: [MovieInput]): [Movie]
}
`
然后在你的突变中,你可以传递一个像
这样的数组
mutation {
addMovies(movies: [{name: 'name1'}, {name: 'name2'}]) {
name
}
}
尚未测试代码,但您明白了
我最终手动解析了正确的模式,因为 JavaScript 数组和 JSON.stringify 字符串不被接受为 graphQL 模式格式。
const id = 5;
const title = 'Title test';
let formattedAttachments = '';
attachments.map(attachment => {
formattedAttachments += `{ id: ${attachment.id}, short_id: "${attachment.shortid}" }`;
// { id: 1, short_id: "abcxyz" }{ id: 2, short_id: "bcdqrs" }
});
// Query
const query = `
mutation {
addChallengeReply(
challengeId: ${id},
title: "${title}",
attachments: [${formattedAttachments}]
) {
id
title
description
}
}
`;
我想到了这个简单的解决方案 - 未使用 JSON。仅使用一个输入。希望对其他人有帮助。
我不得不添加到这个类型:
type Option {
id: ID!
status: String!
products: [Product!]!
}
我们可以添加到变异类型,添加输入如下:
type Mutation {
createOption(data: [createProductInput!]!): Option!
// other mutation definitions
}
input createProductInput {
id: ID!
name: String!
price: Float!
producer: ID!
status: String
}
然后可以使用以下解析器:
const resolvers = {
Mutation: {
createOption(parent, args, ctx, info) {
const status = args.data[0].status;
// Below code removes 'status' from all array items not to pollute DB.
// if you query for 'status' after adding option 'null' will be shown.
// But 'status': null should not be added to DB. See result of log below.
args.data.forEach((item) => {
delete item.status
});
console.log('args.data - ', args.data);
const option = {
id: uuidv4(),
status: status, // or if using babel status,
products: args.data
}
options.push(option)
return option
},
// other mutation resolvers
}
现在您可以使用它来添加一个选项(状态取自数组中的第一项 - 它可以为空):
mutation{
createOption(data:
[{
id: "prodB",
name: "componentB",
price: 20,
producer: "e4",
status: "CANCELLED"
},
{
id: "prodD",
name: "componentD",
price: 15,
producer: "e5"
}
]
) {
id
status
products{
name
price
}
}
}
产生:
{
"data": {
"createOption": {
"id": "d12ef60f-21a8-41f3-825d-5762630acdb4",
"status": "CANCELLED",
"products": [
{
"name": "componentB",
"price": 20,
},
{
"name": "componentD",
"price": 15,
}
]
}
}
}
无需多言,要获得上述结果,您需要添加:
type Query {
products(query: String): [Product!]!
// others
}
type Product {
id: ID!
name: String!
price: Float!
producer: Company!
status: String
}
我知道这不是最好的方法,但我没有在文档中找到这样做的方法。
根据您的要求,我的理解是,如果您有以下代码
const user = {
name:"Rohit",
age:27,
marks: [10,15],
subjects:[
{name:"maths"},
{name:"science"}
]
};
const query = `mutation {
createUser(user:${user}) {
name
}
}`
你一定得到了类似
的东西
"mutation {
createUser(user:[object Object]) {
name
}
}"
而不是预期的
"mutation {
createUser(user:{
name: "Rohit" ,
age: 27 ,
marks: [10 ,15 ] ,
subjects: [
{name: "maths" } ,
{name: "science" }
]
}) {
name
}
}"
如果这是你想要实现的,那么 gqlast 是一个很好的标记函数,你可以使用它来获得预期的结果
只需从 here 中获取 js 文件并将其用作:
const user = {
name:"Rohit",
age:27,
marks: [10,15],
subjects:[
{name:"maths"},
{name:"science"}
]
};
const query = gqlast`mutation {
createUser(user:${user}) {
name
}
}`
存储在变量query
中的结果将是:
"mutation {
createUser(user:{
name: "Rohit" ,
age: 27 ,
marks: [10 ,15 ] ,
subjects: [
{name: "maths" } ,
{name: "science" }
]
}) {
name
}
}"
对于那些不需要为一个请求传入数组,并且愿意为每个突变发出请求的想法的人。 (我正在使用 Vue3,compisition Api,但 React 和 Angular 开发人员仍然可以理解这一点)。
你不能像这样循环突变:
function createProject() {
for (let i = 0; i < state.arrOfItems.length; i++) {
const { mutate: addImplementation } = useMutation(
post_dataToServer,
() => ({
variables: {
implementation_type_id: state.arrOfItems[i],
sow_id: state.newSowId,
},
})
);
addImplementation();
}
}
这会给你一个错误,因为突变必须在 setup() 中。
(这是您将收到的错误:https://github.com/vuejs/vue-apollo/issues/888)
而是创建一个子组件,并将数组映射到父组件中。
在Parent.vue
<div v-for="(card, id) in state.arrOfItems">
<ChildComponent
:id="id"
:card="card"
/>
</div>
在ChildComponent.vue
获得道具并:
const { mutate: addImplementation } = useMutation(
post_dataToServer,
() => ({
variables: {
implementation_id: props.arrOfItems,
id: props.id,
},
})
);
我需要能够在单个请求中创建一个用户并添加它最喜欢的电影(一个对象数组,引用电影集合和他对每部电影的个人评分)。
看起来像这样的东西(伪代码)
var exSchema = `
type Mutation {
addUser(
name: String!
favMovies: [{ movie: String! #ref to movies coll
personal_rating: Int! # this is different for every movie
}]
) : User
}
...
`
在单个请求中执行此操作的 graphql 方法是什么?我知道我可以用多个 mutations/requests 来达到结果,但我想用一个来完成。
将它们作为 JSON 字符串传递。我就是这么做的。
你可以像这样传递一个数组
var MovieSchema = `
type Movie {
name: String
}
input MovieInput {
name: String
}
mutation {
addMovies(movies: [MovieInput]): [Movie]
}
`
然后在你的突变中,你可以传递一个像
这样的数组mutation {
addMovies(movies: [{name: 'name1'}, {name: 'name2'}]) {
name
}
}
尚未测试代码,但您明白了
我最终手动解析了正确的模式,因为 JavaScript 数组和 JSON.stringify 字符串不被接受为 graphQL 模式格式。
const id = 5;
const title = 'Title test';
let formattedAttachments = '';
attachments.map(attachment => {
formattedAttachments += `{ id: ${attachment.id}, short_id: "${attachment.shortid}" }`;
// { id: 1, short_id: "abcxyz" }{ id: 2, short_id: "bcdqrs" }
});
// Query
const query = `
mutation {
addChallengeReply(
challengeId: ${id},
title: "${title}",
attachments: [${formattedAttachments}]
) {
id
title
description
}
}
`;
我想到了这个简单的解决方案 - 未使用 JSON。仅使用一个输入。希望对其他人有帮助。
我不得不添加到这个类型:
type Option {
id: ID!
status: String!
products: [Product!]!
}
我们可以添加到变异类型,添加输入如下:
type Mutation {
createOption(data: [createProductInput!]!): Option!
// other mutation definitions
}
input createProductInput {
id: ID!
name: String!
price: Float!
producer: ID!
status: String
}
然后可以使用以下解析器:
const resolvers = {
Mutation: {
createOption(parent, args, ctx, info) {
const status = args.data[0].status;
// Below code removes 'status' from all array items not to pollute DB.
// if you query for 'status' after adding option 'null' will be shown.
// But 'status': null should not be added to DB. See result of log below.
args.data.forEach((item) => {
delete item.status
});
console.log('args.data - ', args.data);
const option = {
id: uuidv4(),
status: status, // or if using babel status,
products: args.data
}
options.push(option)
return option
},
// other mutation resolvers
}
现在您可以使用它来添加一个选项(状态取自数组中的第一项 - 它可以为空):
mutation{
createOption(data:
[{
id: "prodB",
name: "componentB",
price: 20,
producer: "e4",
status: "CANCELLED"
},
{
id: "prodD",
name: "componentD",
price: 15,
producer: "e5"
}
]
) {
id
status
products{
name
price
}
}
}
产生:
{
"data": {
"createOption": {
"id": "d12ef60f-21a8-41f3-825d-5762630acdb4",
"status": "CANCELLED",
"products": [
{
"name": "componentB",
"price": 20,
},
{
"name": "componentD",
"price": 15,
}
]
}
}
}
无需多言,要获得上述结果,您需要添加:
type Query {
products(query: String): [Product!]!
// others
}
type Product {
id: ID!
name: String!
price: Float!
producer: Company!
status: String
}
我知道这不是最好的方法,但我没有在文档中找到这样做的方法。
根据您的要求,我的理解是,如果您有以下代码
const user = {
name:"Rohit",
age:27,
marks: [10,15],
subjects:[
{name:"maths"},
{name:"science"}
]
};
const query = `mutation {
createUser(user:${user}) {
name
}
}`
你一定得到了类似
的东西"mutation {
createUser(user:[object Object]) {
name
}
}"
而不是预期的
"mutation {
createUser(user:{
name: "Rohit" ,
age: 27 ,
marks: [10 ,15 ] ,
subjects: [
{name: "maths" } ,
{name: "science" }
]
}) {
name
}
}"
如果这是你想要实现的,那么 gqlast 是一个很好的标记函数,你可以使用它来获得预期的结果
只需从 here 中获取 js 文件并将其用作:
const user = {
name:"Rohit",
age:27,
marks: [10,15],
subjects:[
{name:"maths"},
{name:"science"}
]
};
const query = gqlast`mutation {
createUser(user:${user}) {
name
}
}`
存储在变量query
中的结果将是:
"mutation {
createUser(user:{
name: "Rohit" ,
age: 27 ,
marks: [10 ,15 ] ,
subjects: [
{name: "maths" } ,
{name: "science" }
]
}) {
name
}
}"
对于那些不需要为一个请求传入数组,并且愿意为每个突变发出请求的想法的人。 (我正在使用 Vue3,compisition Api,但 React 和 Angular 开发人员仍然可以理解这一点)。
你不能像这样循环突变:
function createProject() {
for (let i = 0; i < state.arrOfItems.length; i++) {
const { mutate: addImplementation } = useMutation(
post_dataToServer,
() => ({
variables: {
implementation_type_id: state.arrOfItems[i],
sow_id: state.newSowId,
},
})
);
addImplementation();
}
}
这会给你一个错误,因为突变必须在 setup() 中。 (这是您将收到的错误:https://github.com/vuejs/vue-apollo/issues/888)
而是创建一个子组件,并将数组映射到父组件中。
在Parent.vue
<div v-for="(card, id) in state.arrOfItems">
<ChildComponent
:id="id"
:card="card"
/>
</div>
在ChildComponent.vue
获得道具并:
const { mutate: addImplementation } = useMutation(
post_dataToServer,
() => ({
variables: {
implementation_id: props.arrOfItems,
id: props.id,
},
})
);