【问题标题】:Combining multiple arrays for querying with MongoDB Java driver使用 MongoDB Java 驱动程序组合多个数组进行查询
【发布时间】:2017-05-18 15:20:21
【问题描述】:

我有以下 JSON:

{"pid":"b00l16vp","categories":{"category1":["factual", "arts culture and the media", "history"]}}
{"pid":"b0079mpp","categories":{"category2":["childrens", "entertainment and comedy", "animation"],"category1":["signed"]}}
{“pid":"b00htbn3"}
{“pid":"b00gdhqw","categories":{"category2":["factual"],"category3":["scotland"],"category4":["lifestyle and leisure", "food and drink"],"category1":["entertainment", "games and quizzes"]}}

我的意图是通过将所有数组组合在一个数组中来使用字符串数组查询类别对象。 我有以下代码:

String [] cats = ["childrens", "signed"]
BasicDBObject theProjections = new BasicDBObject()
for (int i = 1; i <= 5; i++) {
    String identifier = "categories.category" + i
    String cleanIdentifier = "\$" + identifier
    //If the category does not exist, put in a blank category
    def temp = [cleanIdentifier, []]
    theMegaArray.add(new BasicDBObject('$ifNull', temp))
}
//The megaArray is the array created in the above loop which combines all arrays
BasicDBObject theData = new BasicDBObject('$setUnion', theMegaArray)
BasicDBObject theFilter = new BasicDBObject('input', theData)
theFilter.put("as", "megaArray")
//all of the values found in cats should match the megaArray
theFilter.put("cond", new BasicDBObject('$all', ["\$\$megaArray", cats]))
theProjections.put('$filter', theFilter)
FindIterable iterable = collection.find(criteria).projection(theProjections)

到目前为止,我已经使用this question 来编写此代码。 $setUnion 期望所有字段都出现在我的 JSON 中,但是有不同数量的类别数组,因此我使用 $ifNull 用 [] 填充空类别。 $filter 已用于查询 megaArray 上的猫数组。

运行时出现以下错误:

Caused by: com.mongodb.MongoQueryException: Query failed with error code 2 and error message '>1 field in obj: { input: { $setUnion: [ { $ifNull: [ "$categories.category1", [] ] }, { $ifNull: [ "$categories.category2", [] ] }, { $ifNull: [ "$categories.category3", [] ] }, { $ifNull: [ "$categories.category4", [] ] }, { $ifNull: [ "$categories.category5", [] ] } ] }, as: "megaArray", cond: { $all: [ "$$megaArray", [ "factual" ] ] } }'

我不完全确定这意味着什么,因为看起来正确。我还应该注意,类别对象并不总是存在,但我不确定这是否重要。

【问题讨论】:

    标签: java mongodb aggregation-framework mongo-java-driver


    【解决方案1】:

    您可以使用聚合框架实现相同的结果

    为此,您可以先投影数据以创建“megaArray”,然后匹配新数组。

    String [] cats = new String[] {"childrens", "signed"};
    
    List<DBObject> theMegaArray = new ArrayList<>();
    
    BasicDBObject theProjections = new BasicDBObject();
    
    for (int i = 1; i <= 5; i++) {
      String identifier = "categories.category" + i;
      String cleanIdentifier = "$" + identifier;
      //If the category does not exist, put in a blank category
      Object[] temp = new Object[] {cleanIdentifier, new Object[]{}};
      theMegaArray.add(new BasicDBObject("$ifNull", temp));
    }
    
    theProjections.put("_id", 1);
    theProjections.put("pid", 1);
    theProjections.put("categories",1);
    theProjections.put("allCategories", new BasicDBObject("$setUnion", theMegaArray));
    
    BasicDBObject theFilter = new BasicDBObject("allCategories", new BasicDBObject("$all", cats));
    
    List<BasicDBObject> pipeline = new ArrayList<>();
    pipeline.add(new BasicDBObject("$project", theProjections));
    pipeline.add(new BasicDBObject("$match", theFilter));
    
    AggregateIterable iterable = collection.aggregate(pipeline);
    

    上面的代码示例在项目阶段添加了一个名为“allCategories”的新数组,然后匹配这个新文档。

    可以添加另一个投影阶段以从最终输出中删除 allCategories 数组

    【讨论】:

      【解决方案2】:

      您可以使用以下聚合管道。

      Shell 查询供参考:

      db.collection.aggregate([{
          "$project": {
              "pid": 1,
              "categories": 1,
              "filter": {
                  "$eq": [{
                          "$setUnion": [{
                              "$ifNull": ["$categories.category1", []]
                          }, {
                              "$ifNull": ["$categories.category2", []]
                          }, {
                              "$ifNull": ["$categories.category3", []]
                          }, {
                              "$ifNull": ["$categories.category4", []]
                          }, {
                              "$ifNull": ["$categories.category5", []]
                          }]
                      },
                      ["childrens", "signed"]
                  ]
              }
          }
      }, {
          "$match": {
              "filter": true
          }
      }])
      

      Java 代码:

      String[] cats = {"childrens", "signed"};
      
      // Combining the optional categories arrays
       BasicDBList theMegaArray = new BasicDBList();
       for (int i = 1; i <= 5; i++) {
            String identifier = "categories.category" + i;
            String cleanIdentifier = "$" + identifier;
            theMegaArray.add(new BasicDBObject("$ifNull", Arrays.asList(cleanIdentifier, Collections.EMPTY_LIST)));
       }
       BasicDBObject theData = new BasicDBObject("$setUnion", theMegaArray);
      
      // Add equals filter - Compare the arrays and output boolean filter field
       BasicDBObject theFilter = new BasicDBObject("$eq", Arrays.asList(theData, cats));
      
      // Add projections to keep the output fields
       BasicDBObject theProjections = new BasicDBObject();
       theProjections.put("filter", theFilter);
       theProjections.put("pid", 1);
       theProjections.put("categories", 1);
      
      // Add $project stage
       BasicDBObject theProject = new BasicDBObject("$project", theProjections);
      
      // Add $match stage to compare the boolean filter field to true to keep matching documents
       BasicDBObject theMatch = new BasicDBObject("$match", new BasicDBObject("filter", true));
      
      // Add stages to piepline
      BasicDBList pipeline = new BasicDBList();
      pipeline.add(theProject);
      pipeline.add(theMatch);
      
      // Run aggregation
      AggregateIterable iterable = collection.aggregate(pipeline);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多