2014-01-07 6 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

"유형"필드의 유형은 무엇입니까? – evanchooly

+0

.count()를 주석 처리하기 전에 어떤 일이 발생 했습니까? btw, 무슨 몽고범 버전인가요? –

+0

유형은 문자열입니다. 동일한 오류, y 의견은 최종 모델에 카운트가 있기 때문에 발생하지만 결과는 동일합니다. Mongo 버전 : 2.4.8 –

답변

3

집계 직접 MongoDB의 봄 데이터 클래스를 사용하지 않도록하고 사용되는 내 간단한 대답이 표준 MongoDB의 자바 예를 들어, 객체 DBObject/AggregationOutput. 그 이유는 몇 시간 동안 MongoDB Spring 데이터에서 작동하는 기본적인 집계 쿼리를 얻으려고 몇 시간을 보냈다는 것입니다. 그리고 그 중 최신 데이터는 스프링 데이터 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); 

을 보일 것이다 수동 그러나

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); 
} 

즉, 너무 고통스러운하지 않은 결과에서 개체를 변환해야합니다 있지만 편집기 (예 : RoboMongo은)는 자바 코드에서 작동합니다, 당신은 찾을 수 있습니다 Spring Data Aggregation은 잘 작동합니다. Spring을 좋아하고 Mongo Spring Data를 코드의 여러 부분에서 사용합니다. 여러 항목이있는 "$ 그룹"에서 "$ push"를 수행하면 작동하지 않는 것 같습니다. 시간이 갈수록 향상 될 것이라고 확신합니다. 다른 사람들이 이러한 생각을 반복합니다. http://movingfulcrum.tumblr.com/post/61693014502/spring-data-and-mongodb-a-mismatch-made-in-hell - 섹션 4 참조.

해피 코딩!

관련 문제