我的答案很简单:避免直接使用MongoDB的春天数据类,聚集和使用标准MongoDB的Java对象如DBObject/AggregationOutput
。原因是我已经失去了几个小时试图获得任何东西,除了在MongoDB Spring数据中工作的基本聚合查询(并且使用最新的,现在是spring-data-mongodb 1.5.0.RELEASE)。
但是,使用标准的MongoDB Java对象构建聚合查询可能会很痛苦(尤其是嵌套/复杂的情况下),最终创建无数的DBObject groupFields = new BasicDBObject("_id", null);
,代码看起来很乱。
我建议在代码中添加以下3个包装器方法。
protected DBObject dbObj (String key, Object value) {
return new BasicDBObject (key, value);
}
protected DBObject dbObj (Object ... objs) {
DBObject dbObj = new BasicDBObject();
if (objs.length % 2 == 0) {
for (int i = 0; i < objs.length; i+=2) {
dbObj.put((String)objs[i], objs[i+1]);
}
}
return dbObj;
}
protected DBObject dbList (Object ... objs) {
BasicDBList dbList = new BasicDBList();
for (Object obj : objs) {
dbList.add(obj);
}
return (DBObject)dbList;
}
这使您可以轻松地在基于JSON的查询和Java代码之间进行翻译。例如如果你有以下的复杂的查询(从http://docs.mongodb.org/manual/tutorial/aggregation-zip-code-data-set/拍摄)
db.zipcodes.aggregate(
{
$group: {
_id: { state: "$state", city: "$city" },
pop: { $sum: "$pop" }
}
},{
$sort: { pop: 1 }
},{
$group: {
_id: "$_id.state",
biggestCity: { $last: "$_id.city" },
biggestPop: { $last: "$pop" },
smallestCity: { $first: "$_id.city" },
smallestPop: { $first: "$pop" }
}
},{
$project: {
_id: 0,
state: "$_id",
biggestCity: {
name: "$biggestCity",
pop: "$biggestPop"
},
smallestCity: {
name: "$smallestCity",
pop: "$smallestPop"
}
}
});
...那么你的Java代码会是这个样子......
List<DBObject> aggregation = Arrays.asList (
dbObj ("$group", dbObj (
"_id", dbObj ("state", "$state", "city", "$city"),
"pop", dbObj ("$sum", "$post")
)),
dbObj ("$sort", dbObj ("pop", 1)),
dbObj ("$group", dbObj (
"_id", "$_id.state",
"biggestCity", dbObj ("$last", "$_id.city"),
"biggestPop", dbObj ("$last", "$pop"),
"smallestCity", dbObj ("$first", "$_id.city"),
"smallestPop", dbObj ("$first", "$pop")
)),
dbObj ("$project", dbObj (
"_id", 0,
"state", "$_id",
"biggestCity", dbObj ("name", "$biggestCity", "pop", "$biggestPop"),
"smallestCity", dbObj ("name", "$smallestCity", "pop", "$smallestPop")
))
);
// Run aggregation query
DBCollection collection = mongoTemplate.getCollection(COLLECTION_NAME);
AggregationOutput output = collection.aggregate (aggregation);
这样做,这样,如果在工作你的编辑器(如RoboMongo),它会在你的Java代码的工作虽然你将需要手动从结果中,这是不是太痛苦即
List<MyResultClass> results = new ArrayList<MyResultClass>();
Iterator<DBObject> it = output.results().iterator();
while (it.hasNext()) {
DBObject obj = it.next();
MyResultClass result = mongoTemplate.getConverter().read(MyResultClass.class, obj);
results.add(result);
}
但是转换的对象,你会发现Spring Data Aggregation的东西确实可以为你工作。我喜欢Spring,而且我在代码的不同部分使用Mongo Spring Data,它是支持它的聚合支持,例如,在包含多个项目的“$组”中执行“$推送”似乎不起作用。我相信它会随着时间的推移而改进(和更好的文档)。其他人也回应了这些想法,例如http://movingfulcrum.tumblr.com/post/61693014502/spring-data-and-mongodb-a-mismatch-made-in-hell - 请参阅第4部分。
快乐编码!
“type”字段的类型是什么? – evanchooly
在您注释掉.count()之前发生了什么?顺便说一句,这是什么版本的mongodb? –
类型是一个字符串。 同样的错误,y评论,因为计数donts存在于最终模型中,但结果是一样的。 Mongo版本:2.4.8 –