簡體   English   中英

Apollo/GraphQL:如何獲取嵌套元素?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM