我的答案很簡單:避免直接使用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 –