是否可以对通过DBRef存储的数据进行聚合?
2.6 Mongo假设我有这样的交易数据:
{
_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值,如"网页","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 }
} } );
问题是,如果你试图使用一个以$开头的变量,你会得到一个路径错误,要么尝试按它分组,要么尝试通过project使用表达式进行转换。
有什么办法吗?实际上是试图通过聚合将这些数据推送到子集合,在那里对其进行操作。试图避免对数百万条记录进行大型游标操作,以转换数据,以便可以聚合数据。
解决方法如下:具有这样的结构:
{
"_id" : LUUID("144e690f-9613-897c-9eab-913933bed9a7"),
"owner" : {
"$ref" : "person",
"$id" : NumberLong(10)
},
...
...
}
我需要使用"owner"。$ id"字段。但是由于字段名中有"$",我无法使用聚合。我改变了"所有者"。$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}}
])
详细说明在这里- https://dev.to/saurabh73/mongodb-using-aggregation-pipeline-to-extract-dbref-using-lookup-operator-4ekl
不能在聚合框架中使用DBRef
值。相反,您需要使用javascript处理mapReduce,以便访问它们使用的属性命名:
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
。这种用法现在基本上已经被弃用了,如果你觉得你需要一些外部引用,那么你应该用你自己的代码"手动引用"它,或者由其他库实现,这样你就可以以一种更受支持的方式做到这一点。