[英]Apollo/GraphQL: How to get nested elements?
這是我的 mongoDB 的示例文檔。 我需要通過 Apollo/GraphQL 獲取content.en
數組。 但是嵌套對象對我來說是個問題。 en
是語言標簽,所以如果它可以用作變量就太好了。
MongoDB 中的數據
{
"_id" : "9uPjYoYu58WM5Tbtf",
"content" : {
"en" : [
{
"content" : "Third paragraph",
"timestamp" : 1484939404
}
]
},
"main" : "Dn59y87PGhkJXpaiZ"
}
graphQL 結果應該是:
{
"data": {
"article": [
{
"_id": "9uPjYoYu58WM5Tbtf",
"content": [
{
"content" : "Third paragraph",
"timestamp" : 1484939404
}
]
}
]
}
}
這意味着,我需要獲取 ID 和特定於語言的內容數組。
但這不是,我通過以下設置得到了什么:
類型
const ArticleType = new GraphQLObjectType({
name: 'article',
fields: {
_id: { type: GraphQLID },
content: { type: GraphQLString }
}
})
GraphQL 架構
export default new GraphQLSchema({
query: new GraphQLObjectType({
name: 'RootQueryType',
fields: {
article: {
type: new GraphQLList(ArticleType),
description: 'Content of article dataset',
args: {
id: {
name: 'id',
type: new GraphQLNonNull(GraphQLID)
}
},
async resolve ({ db }, args) {
return db.collection('articles').find({ main: args.id }).toArray()
}
}
}
})
})
詢問
{
article(id: "Dn59y87PGhkJXpaiZ") {
_id,
content
}
}
結果
{
"data": {
"article": [
{
"_id": "9uPjYoYu58WM5Tbtf",
"content": "[object Object]"
}
]
}
}
由於您說語言 ISO 代碼應該是一個參數,並且內容取決於語言 ISO 代碼(從現在開始我將其稱為languageTag
),我認為您應該編輯您的架構,使其看起來像這樣:
export default new GraphQLSchema({
query: new GraphQLObjectType({
name: 'RootQueryType',
fields: {
article: {
type: new GraphQLList(ArticleType),
description: 'Content of article dataset',
args: {
id: {
name: 'id',
type: new GraphQLNonNull(GraphQLID)
},
// Edited this part to add the language tag
languageTag: {
name: 'languageTag',
type: new GraphQLNonNull(GraphQLString)
}
},
async resolve ({ db }, args) {
return db.collection('articles').find({ main: args.id }).toArray()
}
}
}
})
})
但是,這仍然不能解決您檢索內容的問題。 我認為您需要將另一種類型添加到您的架構中,稱為ContentType
。
const ContentType = new GraphQLObjectType({
name: 'ContentType',
fields: {
content: {
type: GraphQLString,
resolve: (root, args, context) => root.content[args.languageTag].content
},
timestamp: {
type: GraphQLString,
resolve: (root, args, context) => root.content[args.languageTag].timestamp
}
},
})
我想提出的最后一個問題是,您將article
作為Array
返回。 我建議將其更改為返回單個對象。 最后但並非最不重要的是,您的架構將如下所示:
export default new GraphQLSchema({
query: new GraphQLObjectType({
name: 'RootQueryType',
fields: {
article: {
type: new GraphQLList(ArticleType),
description: 'Content of article dataset',
args: {
id: {
name: 'id',
type: new GraphQLNonNull(GraphQLID)
},
// Edited this part to add the language tag
languageTag: {
name: 'languageTag',
type: new GraphQLNonNull(GraphQLString)
},
// Add the extra fields to the article
fields: {
content: ContentType
}
async resolve ({ db }, args) {
return db.collection('articles').findOne({ main: args.id })
}
}
}
})
})
這段代碼可能有點不對,因為我沒有你的數據庫來測試它。 我認為這是朝着正確方向的良好推動。
您可以使用以下代碼。
String query = {
article(id: "Dn59y87PGhkJXpaiZ") {
_id,
content(language:"en") {
content,
timestamp
}
}
}
const ContentType = new GraphQLObjectType({
name: 'content',
fields: {
content: { type: GraphQLString },
timestamp: { type: GraphQLInt }
}
})
const ArticleType = new GraphQLObjectType({
name: 'article',
fields: {
_id: { type: GraphQLID },
content: {
type: new GraphQLList(ContentType),
args: {
language: {
name: 'language',
type: new GraphQLNonNull(GraphQLString)
}
},
async resolve (args) {
return filter content here by lang
}
}
}
}
})
export default new GraphQLSchema({
query: new GraphQLObjectType({
name: 'RootQueryType',
fields: {
article: {
type: new GraphQLList(ArticleType),
description: 'Content of article dataset',
args: {
id: {
name: 'id',
type: new GraphQLNonNull(GraphQLID)
}
},
async resolve ({ db }, args) {
return db.collection('articles').find({ main: args.id}).toArray()
}
}
}
})
})
Java 示例:
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import graphql.ExecutionResult;
import graphql.GraphQL;
import graphql.schema.*;
import org.bson.Document;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static graphql.Scalars.*;
import static graphql.schema.GraphQLArgument.newArgument;
import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition;
import static graphql.schema.GraphQLObjectType.newObject;
import static graphql.schema.GraphQLSchema.newSchema;
public class GraphQLTest {
private static final ArticleRepository articleRepository;
public static class ArticleRepository {
private final MongoCollection<Document> articles;
ArticleRepository(MongoCollection<Document> articles) {
this.articles = articles;
}
public List<Map<String, Object>> getAllArticles(String id) {
List<Map<String, Object>> allArticles = articles.find(Filters.eq("main", id)).map(doc -> (Map<String, Object>)doc).into(new ArrayList<>());
return allArticles;
}
}
public static void main(String... args) {
String query = "{\n" +
" article(id: \"Dn59y87PGhkJXpaiZ\") {\n" +
" _id,\n" +
" content(language:\"en\") {\n" +
" content,\n" +
" timestamp\n" +
" }\n" +
" }\n" +
"}";
ExecutionResult result = GraphQL.newGraphQL(buildSchema()).build().execute(query);
System.out.print(result.getData().toString());
}
static {
MongoDatabase mongo = new MongoClient().getDatabase("test");
articleRepository = new ArticleRepository(mongo.getCollection("articles"));
}
private static GraphQLSchema buildSchema() {
GraphQLObjectType ContentType = newObject().name("content")
.field(newFieldDefinition().name("content").type(GraphQLString).build())
.field(newFieldDefinition().name("timestamp").type(GraphQLInt).build()).build();
GraphQLObjectType ArticleType = newObject().name("article")
.field(newFieldDefinition().name("_id").type(GraphQLID).build())
.field(newFieldDefinition().name("content").type(new GraphQLList(ContentType))
.argument(newArgument().name("language").type(GraphQLString).build())
.dataFetcher(dataFetchingEnvironment -> {
Document source = dataFetchingEnvironment.getSource();
Document contentMap = (Document) source.get("content");
ArrayList<Document> contents = (ArrayList<Document>) contentMap.get(dataFetchingEnvironment.getArgument("lang"));
return contents;
}).build()).build();
GraphQLFieldDefinition.Builder articleDefinition = newFieldDefinition()
.name("article")
.type(new GraphQLList(ArticleType))
.argument(newArgument().name("id").type(new GraphQLNonNull(GraphQLID)).build())
.dataFetcher(dataFetchingEnvironment -> articleRepository.getAllArticles(dataFetchingEnvironment.getArgument("id")));
return newSchema().query(
newObject()
.name("RootQueryType")
.field(articleDefinition)
.build()
).build();
}
}
我認為問題來自這一行: content: { type: GraphQLString }
。 嘗試將內容提取到另一個GraphQLObjectType
,然后將其作為content
字段傳遞給ArticleType
編輯
嘗試這個:
const ContentType = new GraphQLObjectType({
name: 'content',
fields: {
en: { type: GraphQLList },
it: { type: GraphQLList }
// ... other languages
}
})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.