Apollo/graphql: How To Get Nested Elements?
Solution 1:
You can use below code.
String query = {
article(id: "Dn59y87PGhkJXpaiZ") {
_id,
content(language:"en") {
content,
timestamp
}
}
}
constContentType = newGraphQLObjectType({
name: 'content',
fields: {
content: { type: GraphQLString },
timestamp: { type: GraphQLInt }
}
})
constArticleType = newGraphQLObjectType({
name: 'article',
fields: {
_id: { type: GraphQLID },
content: {
type: newGraphQLList(ContentType),
args: {
language: {
name: 'language',
type: newGraphQLNonNull(GraphQLString)
}
},
async resolve (args) {
return filter content here by lang
}
}
}
}
})
exportdefaultnewGraphQLSchema({
query: newGraphQLObjectType({
name: 'RootQueryType',
fields: {
article: {
type: newGraphQLList(ArticleType),
description: 'Content of article dataset',
args: {
id: {
name: 'id',
type: newGraphQLNonNull(GraphQLID)
}
},
async resolve ({ db }, args) {
return db.collection('articles').find({ main: args.id}).toArray()
}
}
}
})
})
Java Example:
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;
importstatic graphql.Scalars.*;
importstatic graphql.schema.GraphQLArgument.newArgument;
importstatic graphql.schema.GraphQLFieldDefinition.newFieldDefinition;
importstatic graphql.schema.GraphQLObjectType.newObject;
importstatic graphql.schema.GraphQLSchema.newSchema;
publicclassGraphQLTest {
privatestaticfinal ArticleRepository articleRepository;
publicstaticclassArticleRepository {
privatefinal 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(newArrayList<>());
return allArticles;
}
}
publicstaticvoidmain(String... args) {
Stringquery="{\n" +
" article(id: \"Dn59y87PGhkJXpaiZ\") {\n" +
" _id,\n" +
" content(language:\"en\") {\n" +
" content,\n" +
" timestamp\n" +
" }\n" +
" }\n" +
"}";
ExecutionResultresult= GraphQL.newGraphQL(buildSchema()).build().execute(query);
System.out.print(result.getData().toString());
}
static {
MongoDatabasemongo=newMongoClient().getDatabase("test");
articleRepository = newArticleRepository(mongo.getCollection("articles"));
}
privatestatic GraphQLSchema buildSchema() {
GraphQLObjectTypeContentType= newObject().name("content")
.field(newFieldDefinition().name("content").type(GraphQLString).build())
.field(newFieldDefinition().name("timestamp").type(GraphQLInt).build()).build();
GraphQLObjectTypeArticleType= newObject().name("article")
.field(newFieldDefinition().name("_id").type(GraphQLID).build())
.field(newFieldDefinition().name("content").type(newGraphQLList(ContentType))
.argument(newArgument().name("language").type(GraphQLString).build())
.dataFetcher(dataFetchingEnvironment -> {
Documentsource= dataFetchingEnvironment.getSource();
DocumentcontentMap= (Document) source.get("content");
ArrayList<Document> contents = (ArrayList<Document>) contentMap.get(dataFetchingEnvironment.getArgument("lang"));
return contents;
}).build()).build();
GraphQLFieldDefinition.BuilderarticleDefinition= newFieldDefinition()
.name("article")
.type(newGraphQLList(ArticleType))
.argument(newArgument().name("id").type(newGraphQLNonNull(GraphQLID)).build())
.dataFetcher(dataFetchingEnvironment -> articleRepository.getAllArticles(dataFetchingEnvironment.getArgument("id")));
return newSchema().query(
newObject()
.name("RootQueryType")
.field(articleDefinition)
.build()
).build();
}
}
Solution 2:
Since you said that the language ISO code should be a parameter and that the content is depending on a language ISO code (I'll call it languageTag
from now on), I figured that you should edit your schema to look something like this:
export defaultnew 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()
}
}
}
})
})
However, this still does not fix your issue of retrieving the content. I reckon that you need to add another type to your schema called ContentType
.
constContentType=newGraphQLObjectType({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
}
},})
One final issue I would like to bring up is that you are returning a single article
as an Array
. I would suggest to change this to return a single object. Last but not least, your schema would look something like this:
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 })
}
}
}
})
})
This code could be a little bit off, since I do not have your database to test it. I think that it is a good push in the right direction.
Solution 3:
I think the problem comes from this line:
content: { type: GraphQLString }
. Try extracting content to another GraphQLObjectType
and then pass it to ArticleType
as content
field
Edit
Try this:
const ContentType = new GraphQLObjectType({
name: 'content',
fields: {
en: { type: GraphQLList },
it: { type: GraphQLList }
// ... other languages
}
})
Post a Comment for "Apollo/graphql: How To Get Nested Elements?"