是否可以聚合通过DBRef存储的数据?
Mongo 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")
}
诀窍是“源”本质上是多态的 - 它可能是不同的$ ref值,例如“webpage”,“call_center”等,它们也有不同的ObjectIds。例如,DBRef(“网页”,ObjectId(“1”))和DBRef(“网页”,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 }
} } );
诀窍是你尝试使用以$开头的变量,尝试按其分组或尝试通过项目使用表达式进行转换,从而获得路径错误。
有什么办法吗?实际上试图通过聚合将这些数据推送到子集合以在那里进行操作。试图避免在数百万条记录上进行大型游标操作来转换数据,以便我可以聚合它。
答案 0 :(得分:1)
Mongo 4.通过以下方式解决了此问题: 具有这种结构:
{
"_id" : LUUID("144e690f-9613-897c-9eab-913933bed9a7"),
"owner" : {
"$ref" : "person",
"$id" : NumberLong(10)
},
...
...
}
我需要使用“ owner。$ id”字段。但是由于字段名中的“ $”,我无法使用聚合。 我使用以下代码段转换了“ owner。$ id”->“ owner”:
db.activities.find({}).aggregate([
{
$addFields: {
"owner": {
$arrayElemAt: [{ $objectToArray: "$owner" }, 1]
}
}
},
{
$addFields: {
"owner": "$owner.v"
}
},
{"$group" : {_id:"$owner", count:{$sum:1}}},
{$sort:{"count":-1}}
])
答案 1 :(得分:0)
您不能将DBRef
值用于聚合框架。相反,您需要使用mapReduce的JavasScript处理来访问他们使用的属性命名:
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 }
}
)
你根本不应该使用DBRef
。现在基本上已经弃用了这个用法,如果你觉得需要一些外部引用,那么你应该用自己的代码“手动引用”它或者用其他库来实现,你可以用更加支持的方式来实现。