首页 文章

如何在Java中实现此MongoDB聚合

提问于
浏览
1

我有以下工作MongoDB聚合shell命令:

db.followrequests.aggregate([{
    $match: {
        _id: ObjectId("551e78c6de5150da91c78ab9")
    }
}, {
    $unwind: "$requests"
}, {
    $group: {
        _id: "$_id",
        count: {
            $sum: 1
        }
    }
}]);

哪个回报:

{“_ id”:ObjectId(“551e78c6de5150da91c78ab9”),“count”:7}

我需要在Java中实现这一点,我正在尝试以下方法:

List<DBObject> aggregationInput = new ArrayList<DBObject>();

BasicDBObject match = new BasicDBObject();
match.put("$match", new BasicDBObject().put("_id",new ObjectId(clientId)));
aggregationInput.add(match);

BasicDBObject unwind = new BasicDBObject();
unwind.put("$unwind", "$requests");
aggregationInput.add(unwind);

BasicDBObject groupVal = new BasicDBObject();
groupVal.put("_id", "$_id");
groupVal.put("count", new BasicDBObject().put("$sum", 1));

BasicDBObject group = new BasicDBObject();
group.put("$group", groupVal);
aggregationInput.add(group);

AggregationOutput output = followRequestsCol.aggregate(aggregationInput);
for (DBObject result : output.results()) {
    System.out.println(result);
}

我得到一个例外:

mongodb匹配过滤器必须是对象中的表达式 .

你能帮我识别一下上面代码中的错误吗?谢谢!

3 回答

  • 0

    尝试打印 aggregationInput 的值,您将意识到 .put() 不返回 BasicDBObject ,而只返回与您更新的密钥关联的先前值 . 因此,当你这样做时:

    match.put("$match", new BasicDBObject().put("_id",new ObjectId(clientId)));
    

    您实际上将 $match 设置为 null ,因为 new BasicDBObject().put("_id",new ObjectId(clientId)) 返回 null .

    将代码更新为:

    List <DBObject> aggregationInput = new ArrayList <DBObject> ();
    
    BasicDBObject match = new BasicDBObject();
    BasicDBObject matchQuery = new BasicDBObject();
    matchQuery.put("_id", new ObjectId());
    match.put("$match", matchQuery);
    aggregationInput.add(match);
    
    BasicDBObject unwind = new BasicDBObject();
    unwind.put("$unwind", "$requests");
    aggregationInput.add(unwind);
    
    BasicDBObject groupVal = new BasicDBObject();
    groupVal.put("_id", "$_id");
    groupVal.put("count", new BasicDBObject().put("$sum", 1));
    
    BasicDBObject group = new BasicDBObject();
    group.put("$group", groupVal);
    aggregationInput.add(group);
    
    AggregationOutput output = followRequestsCol.aggregate(aggregationInput);
    for (DBObject result : output.results()) {
        System.out.println(result);
    }
    

    或者,稍微更具可读性,使用流利的 BasicDBObjectBuilder

    final DBObject match = BasicDBObjectBuilder.start()
                                               .push("$match")
                                                   .add("_id", new ObjectId())
                                               .get();
    aggregationInput.add(match);
    

    它应该工作正常 .

  • 1

    每个 {} 必须是新的 DBObject . 使用 .append(key,value) 方法也可以更优雅 .

    试试这个:

    List<DBObject> pipeline = new ArrayList<DBObject>(Arrays.asList(
        new BasicDBObject("$match", new BasicDBObject("_id", 
            new ObjectId("551e78c6de5150da91c78ab9"))), 
        new BasicDBObject("$unwind", "$requests"),
        new BasicDBObject("$group", 
            new BasicDBObject("_id","$_id").append("count", new BasicDBObject("$sum", 1)))));
    
    AggregationOutput output = followRequestsCol.aggregate(pipeline);
    for (DBObject result : output.results()) {
        System.out.println(result);
    }
    
  • 1

    这是最终的工作版本,基于以上建议//使用mongodb聚合框架来确定关注者的数量Integer returnCount = 0;列出aggregationInput = new ArrayList();

    BasicDBObject match = new BasicDBObject();
        BasicDBObject matchQuery = new BasicDBObject();
        matchQuery.put("_id", new ObjectId(clientId));
        match.put("$match", matchQuery);
        aggregationInput.add(match);
    
        BasicDBObject unwind = new BasicDBObject();
        unwind.put("$unwind", "$requests");
        aggregationInput.add(unwind);
    
        BasicDBObject groupVal = new BasicDBObject();
        groupVal.put("_id", null);
        BasicDBObject sum = new BasicDBObject();
        sum.put("$sum", 1);
        groupVal.put("count", sum);
        BasicDBObject group = new BasicDBObject();
        group.put("$group", groupVal);
        aggregationInput.add(group);
    
        AggregationOutput output = followRequestsCol.aggregate(aggregationInput);
        for (DBObject result : output.results()) {
            returnCount = (Integer) result.get("count");
            break;
        }
        return returnCount;
    

相关问题