是否可以对通过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("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 }
} } );诀窍是,当您尝试使用以$开头的变量时,您会遇到路径错误,无论是通过尝试对其进行分组,还是尝试通过project使用表达式进行转换。
有办法做到这一点吗?实际上是试图通过聚合将这些数据推送到一个子集合中,以便在那里对其进行操作。尝试避免对数百万条记录执行大型游标操作来转换数据,以便对其进行聚合。
发布于 2015-07-09 08:03:41
您不能在聚合框架中使用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。这种用法现在基本上已经被弃用了,如果你觉得你需要一些外部引用,那么你应该用你自己的代码“手动引用”它,或者用其他库实现它,这样你可以用一种更受支持的方式来做到这一点。
发布于 2020-04-27 05:10:28
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}}
])https://stackoverflow.com/questions/31299176
复制相似问题