2017-10-25 9 views
1

이것은 내 mongoDB의 예제 문서입니다. Apollo/GraphQL을 통해 content.en 배열을 가져와야합니다. 하지만 중첩 된 객체가 나를 위해 문제가되고 있습니다. en이 언어 태그이므로 변수로 사용할 수 있다면 좋을 것입니다.Apollo/GraphQL : 중첩 된 요소를 얻는 방법?

데이터

{ "_id" : "9uPjYoYu58WM5Tbtf", "content" : { "en" : [ { "content" : "Third paragraph", "timestamp" : 1484939404 } ] }, "main" : "Dn59y87PGhkJXpaiZ" } 

MongoDB를
에서 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() 
     } 
     } 
    } 
    }) 
}) 

Q : 나는 다음 설치를 얻고 무엇을


그러나 이것은 아니다, content: { type: GraphQLString } : uery

{ 
    article(id: "Dn59y87PGhkJXpaiZ") { 
    _id, 
    content 
    } 
} 

결과

{ 
    "data": { 
    "article": [ 
     { 
     "_id": "9uPjYoYu58WM5Tbtf", 
     "content": "[object Object]" 
     } 
    ] 
    } 
} 
+0

정확히 어떤 쿼리가 반환 할 것으로 예상합니까? 질문에 그것을 추가 할 수 있습니까? – DevNebulae

+0

@DevNebulae 이미 게시했습니다. 두 번째 코드 블록을 참조하십시오. "graphQL 결과는" – user3142695

+1

이어야합니다. 당신이 두 개의 args를 필요로한다고 생각합니다. id 인수는 루트 해결에 대한 기사를 필터링하고 language arg는 sub resolve에 대한 내용을 필터링합니다. 그래서 mongo 질의는 모든 언어 내용을 가진 id와 일치하는 모든 기사를 반환 할 것이고 graphql은 언어 arg에 기반한 내용을 반환 할 것입니다. 또한 컨텐츠를 스키마에 맵핑하십시오. – Veeram

답변

1

아래 코드를 사용할 수 있습니다.

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() 
     } 
     } 
    } 
    }) 
}) 

자바 예 :

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(); 
    } 
} 
+0

힌트가 있으십니까? https://stackoverflow.com/questions/46929327/how-to-nest-two-graphql-queries-in-a-schema – user3142695

+0

이 질문은이 질문과 매우 비슷하게 보입니다. 구조를 새 것으로 바 꾸었습니까? 지금 새로운 컬렉션 컨텐츠가 있습니까? 나는 여기에 제공된 대답이 어느 정도는 효과가 있다고 믿는다. 차이점은 무엇입니까? – Veeram

+0

예제 코드에서 약간 변경되었습니다. 나는 그 둥지에 정말로 머물렀다. 처음에는 아주 똑같은 문제가있는 것 같아서 아주 간단하다고 생각했습니다. – user3142695

0

나는 문제가이 라인에서 온다 생각합니다. 당신이 언어 ISO 코드는 매개 변수를해야한다고 말했다 때문에

const ContentType = new GraphQLObjectType({ 
    name: 'content', 
    fields: { 
    en: { type: GraphQLList }, 
    it: { type: GraphQLList } 
    // ... other languages 
    } 
}) 
+0

저에게는 두 가지 문제점이 있습니까? 필드'en'은 가변적입니다. 'de' 또는'it'도있을 수 있습니다. 그래서 올바른 langugage 객체를 얻기 위해 변수를 사용해야합니다. 나는 그것에 갇혀있다. 그리고 두 번째로, 이것은 배열이므로,'GraphQLString'은 여기서 작동하지 않을 것입니다, 그렇습니까? 더 나은 이해를 위해 몇 가지 코드를 게시 해주십시오. – user3142695

+0

@ user3142695 방금 답변을 업데이트했습니다. –

0

그 : 다른 GraphQLObjectType에 내용을 추출 시도하고 content 필드

ArticleType에 전달 편집

이 시도 내용이 인데 언어 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 
    } 
    }, 
}) 

마지막으로 문제는 당신이 Array 같은 단일 article를 반환하는 것입니다. 단일 객체를 반환하도록 변경하는 것이 좋습니다. 마지막으로, 스키마는 다음과 같이 보일 것이다 : 나는 그것을 테스트하기 위해 데이터베이스를 가지고 있지 않기 때문에

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 }) 
     } 
     } 
    } 
    }) 
}) 

이 코드는 조금 떨어져있을 수 있습니다.나는 그것이 올바른 방향으로 좋은 추진력이라고 생각합니다.

+0

언어 필드는 여러 콘텐츠 개체가 있으므로 배열입니다. 예제에서는 하나의 객체 만 있습니다. 그러나 나는 그 배열을 위해 갈 필요가있다. – user3142695

+0

@ user3142695 문제의 스키마를 제공해 주시겠습니까? 나는 우리가 퍼즐의 큰 부분을 놓치고 있다고 생각한다. – DevNebulae

+0

누락 된 점은 무엇입니까? 나는 내가 가진 모든 것을 게시했다고 생각합니다 ... – user3142695