我正在使用Play!框架morphia-mongodb模块,我发现它有很好的内置插件来进行组聚合。不幸的是,所有示例仅显示按固定字段分组/聚合,而我需要按计算字段聚合:按日分组的时间戳。我想知道是否有人知道正确的方法吗?
我知道我可以诉诸原生地图/减少(本身需要花一点时间才能弄明白,所以我在这里发帖以供参考,使用电影和放映时间):
DBCollection coll = Movie.col();
String map = "function() { " +
(this.showtime.getMonth() + 1) + '/' + this.showtime.getDate()}; "
+ "var key = {date: this.showtime.getFullYear() + '/'
+ (this.showtime.getMonth() + 1)
+ '/' + this.showtime.getDate()}; "
+ "emit(key, {count: 1}); }";
String reduce = "function(key, values) { var sum = 0; "
+ " values.forEach( function(value) {sum += value['count'];} );"
+ " return {count: sum}; }";
String output = "dailyShowingCount";
MapReduceOutput out = coll.mapReduce(
map, reduce, output, MapReduceCommand.OutputType.REPLACE, null);
SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd");
for (Iterator<DBObject> itr = out.results().iterator(); itr.hasNext();) {
DBObject dbo = itr.next();
String compoundKeyStr = dbo.get("_id").toString();
String compoundValStr = dbo.get("value").toString();
DBObject compKey = (DBObject)JSON.parse(compoundKeyStr);
DBObject compVal = (DBObject)JSON.parse(compoundValStr);
//don't know why count returns as a float, but it does, so i need to convert
Long dCount = new Double(
Double.parseDouble(compVal.get("count").toString())
).longValue();
Date date = df.parse(compKey.get("date").toString());
}
但是如果已经有一种优雅的内置方式与morphia模块进行这种聚合,我想用它代替。我有一个想法是在我的java类中创建一个虚拟字段(例如“getDay()”),然后按此分组/聚合。有没有人有这方面的经验?
答案 0 :(得分:0)
最简单的方法是在模型中创建派生列并将其保存到数据库中。
@Entity Movie extends Model {
public Date showTime;
private Date showTimeDate;
@OnUpdate
@OnAdd
void calcShowTimeDate() {
Calendar c = Calendar.getInstance();
c.setTime(showTime);
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MILLISECOND, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
showTimeDate = c.getTime()
}
}
然后,您可以按照http://www.playframework.org/modules/morphia-1.2.4d/statistics
上的说明在showTimeDate
列进行汇总