Jef*_*eff 5 mongodb dbref aggregation-framework
是否可以聚合通过 DBRef 存储的数据?
蒙戈2.6
假设我有如下交易数据:
{
_id : ObjectId(...),
user : DBRef("user", ObjectId(...)),
product : DBRef("product", ObjectId(...)),
source : DBRef("website", ObjectId(...)),
quantity : 3,
price : 40.95,
total_price : 122.85,
sold_at : ISODate("2015-07-08T09:09:40.262-0700")
}
Run Code Online (Sandbox Code Playgroud)
诀窍是“source”本质上是多态的 - 它可能是不同的 $ref 值,例如“webpage”、“call_center”等,它们也有不同的 ObjectId。例如,DBRef("webpage", ObjectId("1")) 和 DBRef("webpage",ObjectId("2")) 将是事务发起的两个不同网页。
我想最终按来源在一段时间内(例如一个月)进行汇总:
db.coll.aggregate( { $match : { sold_at : { $gte : start, $lt : end } } },
{ $project : { source : 1, total_price : 1 } },
{ $group : {
_id : { "source.$ref" : "$source.$ref" },
count : { $sum : $total_price }
} } );
Run Code Online (Sandbox Code Playgroud)
诀窍是,您在尝试使用以 $ 开头的变量时会遇到路径错误,无论是尝试按变量分组还是尝试通过项目使用表达式进行转换。
有办法做到这一点吗?实际上尝试通过聚合将这些数据推送到子集合以对其进行操作。尝试避免对数百万条记录进行大型游标操作来转换数据,以便我可以聚合它。
您不能将DBRef值与聚合框架一起使用。相反,您需要使用MapReduce的 JavaScript 处理来访问它们使用的属性命名:
db.coll.mapReduce(
function() {
emit( this.source.$ref, this["total_price"] )
},
function(key,values) {
return Array.sum( values );
},
{
"query": { "sold_at": { "$gte": start, "$lt": end } },
"out": { "inline": 1 }
}
)
Run Code Online (Sandbox Code Playgroud)
你真的不应该使用DBRef。现在基本上已弃用该用法,如果您觉得需要一些外部引用,那么您应该使用自己的代码“手动引用”它或由其他库实现,您可以通过更受支持的方式来执行此操作。