2017-10-25 16 views
1

これは私のmongoDBのサンプルドキュメントです。 Apollo/GraphQL経由でcontent.en配列を取得する必要があります。しかし、ネストされたオブジェクトは私のために問題を起こしています。 enは言語タグなので、これを変数として使用することができれば素晴らしいでしょう。 graphQL結果がでなければなりませんMongoDBのでApollo/GraphQL:ネストされた要素を取得するには?

データ

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

{ 
    "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私はすでにそれを投稿しました。 2番目のコードブロックを参照してください。 "graphQLの結果は" – user3142695

+1

"でなければなりません。私は、root解決の記事をフィルタリングするid引数とsub resolveのコンテンツをフィルタする言語引数が必要だと思います。したがって、mongo queryは、すべての言語コンテンツを持つ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() 
     } 
     } 
    } 
    }) 
}) 

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

私には2つの問題がありますか?フィールド '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

複数のコンテンツオブジェクトがあるため、言語フィールドは配列です。私の例では、オブジェクトは1つしかありません。しかし、私は配列のために行く必要があります。 – user3142695

+0

@ user3142695問題のスキーマを教えてください。パズルの大きな部分が欠けていると思う。 – DevNebulae

+0

あなたは何が欠けていますか?私は私が持っているすべてを投稿したと思う... – user3142695

関連する問題