代码之家  ›  专栏  ›  技术社区  ›  Truerick

将Java Spring代码从AggregationOutput更改为DBCollection聚合方法

  •  0
  • Truerick  · 技术社区  · 6 年前

    我正在更新一个2014 Java项目,其中包含最新的库,MongoDB Java驱动程序从3.0改为3.6。大多数代码已经更新,但是有一个非常复杂的特定查询,这给我带来了问题。

    文件是这样的

    {
        "_id" : ObjectId("58750a67ae28bc28e0705b0f"),
        "info": "description",
        "parentId", "variable-id-here"
        "issues": [
            {"name": "a", "closed": true},
            {"name": "b", "closed": false},
            {"name": "c", "closed": true}
        ],
        "bugs": [
            {"name": "d", "closed": false},
            {"name": "e", "closed": false},
            {"name": "f", "closed": true}
        ],
        "errors": [
            {"name": "g", "closed": true},
            {"name": "h", "closed": true},
            {"name": "i", "closed": false}
        ]
    }
    

    (即使数组中的元素相似,也不能用额外的“type”键将它们分组到文档中的单个数组中,键的值为[问题、错误、错误],但这不是重点)

    老剧本就是这个

    List<DBObject> aggregators = new ArrayList<>();
    DBObject match = new BasicDBObject("$match", new BasicDBObject("parentId", myId));
    DBObject project = new BasicDBObject();
    List<String> domains = Arrays.asList("issues", "bugs", "errors");
    
    for (Iterator<String> d = domains.iterator(); d.hasNext();) {
        String domain = d.next();
        //Reset values
        aggregators = new ArrayList<>();
        // Define MongoDB "$project" to find 'true' values on 'closed' flags
        project = new BasicDBObject("$project", new BasicDBObject("closedProblems", 
            new BasicDBObject("$filter",
                new BasicDBObject("input", "$"+domain)
                    .append("as", "myObject")
                    .append("cond", new BasicDBObject("$eq",
                        Arrays.<Object> asList("$$myObject.closed", true)
                    )
                )
            )
        ));
    
        aggregators.add(match);
        aggregators.add(project);
        //db defined before. AggregationOutput is deprecated so must be changed
        AggregationOutput output = db.getCollection("myColl").aggregate(aggregators);
    
        // Now I can iterate results
        for (DBObject result : output.results()) {
            // ...
        }
    }
    

    我试图使用项目、表达式等,但找不到用新聚合方法复制MongoDB项目的方法。

    最终结果应该使用 mongoTemplate . 任何方法 执行聚合以加入新的项目指南

    1 回复  |  直到 6 年前
        1
  •  1
  •   Truerick    6 年前

    在3.6驱动程序中使用以下代码。

    DBCursor output = (DBCursor) db.getCollection("myColl").aggregate(aggregators, AggregationOptions.builder().build());
    for (Iterator<DBObject> r = output.iterator(); output.hasNext();) {
          DBObject result = r.next();
          ...
    }
    

    更新:

    import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
    import static org.springframework.data.mongodb.core.aggregation.ArrayOperators.Filter.filter;
    import static org.springframework.data.mongodb.core.aggregation.ComparisonOperators.Eq.valueOf;
    import org.springframework.data.mongodb.core.query.Criteria;
    import org.springframework.data.mongodb.core.aggregation.*;
    
    List<AggregationOperation> aggregators;
    MatchOperation match = Aggregation.match(Criteria.where("parentId").is(myId));
    List<String> domains = Arrays.asList("issues", "bugs", "errors");
    for (Iterator<String> d = domains.iterator(); d.hasNext();) {
         String domain = d.next();
         aggregators = new ArrayList<>();
         ProjectionOperation project = project().and(filter(domain)
                            .as("myObject")
                            .by(valueOf(
                                    "myObject.closed")
                                    .equalToValue(
                                           true)))
                            .as("closedProblems");
         aggregators.add(match);
         aggregators.add(project);
         Aggregation aggregation = newAggregation(aggregators).withOptions(newAggregationOptions().cursor(new Document()).build());
         AggregationResults<Document> results = mongoTemplate.aggregate(aggregation, "myColl", Document.class );
         for (Document result : results) {
                        // ...
        }
    }