使用Aggrerate

时间:2016-10-28 14:49:09

标签: java mongodb mongodb-query aggregation-framework

我正在尝试学习如何在Java中使用Mongo,并且能够进行一些简单的查询,但是我遇到了使用聚合运算符的问题。

文档结构很简单,如下所示:

{
    "_id" : ObjectId("57dbe94f0507a4d8710ac5b2"),
    "name" : "Name1",
    "age" : 23
}
{
    "_id" : ObjectId("57dbe9750507a4d8710ac5b3"),
    "name" : "Name2",
    "age" : "String for examble"
}
{
    "_id" : ObjectId("57dbee630507a4d8710ac5b5"),
    "name" : "Name3",
    "age" : 24
}

我想要做的就是获取集合中ages的平均值(名称示例)。

简单地使用mongo我可以通过以下咨询得到理想的结果:

db.example.aggregate([
    {
        $group: {
            _id: null, 
            averageAge: { $avg: "$age" }
        }
    }
]);

我尝试了以下内容:

BasicDBObject groupFields = new BasicDBObject("_id", "null");
BasicDBObject media = new BasicDBObject("$avg", "$age");
groupFields.put("mediaIdade", media);
BasicDBObject group = new BasicDBObject("$group", groupFields );
AggregateIterable<org.bson.Document> agregate = db.getCollection("exemplo").aggregate(Arrays.asList (group));

这几乎是直接翻译但得到"java.lang.NoSuchMethodError: org.bson.codecs.BsonTypeClassMap.keys()Ljava/util/Set;",这并不奇怪。

但我无法将其转换为Java。我已检查并找到 this question ,但由于使用$unwind等操作符而无法理解。所以我试图让查询尽可能简单,以便更好地理解聚合的Java框架是如何工作的。

有人可以帮忙吗?

3 个答案:

答案 0 :(得分:2)

尝试这样的事情。

MongoCollection<Document> dbCollection = db.getCollection("example", Document.class);
AggregateIterable<org.bson.Document> aggregate = dbCollection.aggregate(Arrays.asList(Aggregates.group("_id", new BsonField("averageAge", new BsonDocument("$avg", new BsonString("$age"))))));
Document result = aggregate.first();
double age = result.getDouble("averageAge");

输入:

{ "_id" : ObjectId("58136d6ed96cc299c224d529"), "name" : "Name1", "age" : 23 }
{ "_id" : ObjectId("58136d6ed96cc299c224d52a"), "name" : "Name2", "age" : 26 }
{ "_id" : ObjectId("58136d6ed96cc299c224d52b"), "name" : "Name3", "age" : 24 }

输出:

24.333333333333332

答案 1 :(得分:0)

我注意到你的代码中有一个小错字:

db.getCollection("exemplo").aggregate(Arrays.asList (group));

应该是example而不是examplo

翻译工作mongo表达式的最简单方法是使用Document.parse方法。

在你的情况下,它可能是:

db.getCollection("exemplo").aggregate(Arrays.asList(
   Document.parse("{ $group: { _id: null, averageAge: { $avg: '$age' } } }")
));

你的impl几乎是正确的,两个小问题:

  • "null"字符串替换为null
  • 使用"averageAge"代替"mediaIdade"

    BasicDBObject groupFields = new BasicDBObject("_id", null);
    BasicDBObject media = new BasicDBObject("$avg", "$age");
    groupFields.put("averageAge", media);
    BasicDBObject group = new BasicDBObject("$group", groupFields );
    AggregateIterable<org.bson.Document> agregate = db.getCollection("exemple").aggregate(Arrays.asList (group));
    

获得结果:

   agregate.first().getDouble("averageAge");

答案 2 :(得分:0)

试试这个:

DBObject groupFields = new BasicDBObject( "_id", 0);
groupFields.put("average", new BasicDBObject( "$avg", "$age"));
DBObject group = new BasicDBObject("$group", groupFields);
AggregationOutput output = db.getCollection("exemplo").aggregate(group);
Iterable<DBObject> list = output.results();

如果需要,可以在查询中添加过滤器,您可以添加匹配参数:

DBObject match = new BasicDBObject();
match.put("age", new BasicDBObject("$gte", 25));
DBObject groupFields = new BasicDBObject( "_id", 0);
groupFields.put("average", new BasicDBObject( "$avg", "$age"));
DBObject group = new BasicDBObject("$group", groupFields);
AggregationOutput output = db.getCollection("exemplo").aggregate(match, group);
Iterable<DBObject> list = output.results();