2014-01-07 53 views
0

我正在使用Spring-Data MongoDB aggregation framework聚合框架 - 組操作throw NumberFormatException

下面是一個代碼示例:

Aggregation agg = Aggregation.newAggregation(
    match(Criteria.where("type").is("PROMO")), 
    group("locale")//.count().as("counts") 
); 


AggregationResults<Message> results = mongoTemplate.aggregate(agg, "message", Message.class); 
return results.getMappedResults(); 

投擲:

org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type java.math.BigDecimal for value 'CL'; nested exception is java.lang.NumberFormatException 

CL是在區域字段中的值,但我不明白爲什麼拋出該異常。我使用了一個類似documentation的例子。

解決:

Aggregation agg = Aggregation.newAggregation(
      match(Criteria.where("type").is("PROMO")), 
      group("created", "text").addToSet("locale").as("countries").addToSet("device.deviceType").as("platforms").count().as("count") 
    ); 

我嘗試蒙戈控制檯上的一個簡單的例子。之後,將操作映射到構建器。 我不喜歡爲什麼以前不工作。如果有人能清除這個問題會很好。

模型「消息」:

{ "_id" : "90.0", "device" : { "_id" : "5faf92fd-37f2-4d42-a01a-dd1abce0c1af", "deviceType" : "iPhone", "countryId" : "AR" }, "text" : "Text", "created" : ISODate("2014-01-03T15:56:27.096Z"), "status" : "SENT", "type" : "PROMO" } 
+0

「type」字段的類型是什麼? – evanchooly

+0

在您註釋掉.count()之前發生了什麼?順便說一句,這是什麼版本的mongodb? –

+0

類型是一個字符串。 同樣的錯誤,y評論,因爲計數donts存在於最終模型中,但結果是一樣的。 Mongo版本:2.4.8 –

回答

3

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

快樂編碼!