使用DBRef进行MongoDB聚合

时间:2015-07-08 17:06:53

标签: mongodb aggregation-framework dbref

是否可以聚合通过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 }
                      } } );

诀窍是你尝试使用以$开头的变量,尝试按其分组或尝试通过项目使用表达式进行转换,从而获得路径错误。

有什么办法吗?实际上试图通过聚合将这些数据推送到子集合以在那里进行操作。试图避免在数百万条记录上进行大型游标操作来转换数据,以便我可以聚合它。

2 个答案:

答案 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}}
])

此处有详细说明-https://dev.to/saurabh73/mongodb-using-aggregation-pipeline-to-extract-dbref-using-lookup-operator-4ekl

答案 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。现在基本上已经弃用了这个用法,如果你觉得需要一些外部引用,那么你应该用自己的代码“手动引用”它或者用其他库来实现,你可以用更加支持的方式来实现。