如何计算两个查询的差异?

时间:2015-04-15 20:38:39

标签: mongodb mongodb-query aggregation-framework set-difference

我有一个包含一组文档的MongoDB集合。每个文档都有一个ISODate date和一个整数id(不是_id)。如果集合中的文档中包含字段值id: X,则date: D的{​​{1}}被认为存在。所以,例如:

{ id: X, date: D }

我希望随着时间的推移跟踪{ id: 1, date: 1/1/2000 } { id: 1, date: 1/2/2000 } { id: 1, date: 1/3/2000 } { id: 1, date: 1/4/2000 } { id: 2, date: 1/2/2000 } { id: 2, date: 1/3/2000 } { id: 3, date: 1/3/2000 } ,因为它们是日常创建和销毁的。使用上述数据,在1/1/2000至1/4/2000的日期范围内:

id

我认为解决这个问题的最佳方法是逐日循环,查看今天和第二天之间存在的1/1/2000: id 1 is created 1/2/2000: id 2 is created 1/3/2000: id 3 is created 1/4/2000: id 2 is destroyed 1/4/2000: id 3 is destroyed ,并执行一组差异。例如,要获得在1/2/2000创建和销毁的一组id,我需要在两天之间执行两组数组差异:

id

我可以使用var A = [ <ids that exist on 1/1/2000> ]; var B = [ <ids that exist on 1/2/2000> ]; var created_set = set_difference(B, A); // Those in B and not in A var destroyed_set = set_difference(A, B); // Those in A and not in B 命令获取find()A的游标,但我不知道如何在两个游标之间执行B

我的另一个选择是使用聚合管道,但我无法考虑如何以我可以使用set_difference运算符的方式来表达管道。

作为一名MongoDB新手,我确信我以错误的方式思考问题。当然这是可以做到的事情?我错过了什么?

2 个答案:

答案 0 :(得分:2)

db.mystuff.aggregate([
    {$group: {_id: '$id', created: {$first: '$date'}, destroyed: {$last: '$date'}}}
])

答案 1 :(得分:1)

假设您有以下样本集:

db.collection.insert([
    { id: 1, date: ISODate("2000-01-01") },
    { id: 1, date: ISODate("2000-01-02") },
    { id: 1, date: ISODate("2000-01-03") },
    { id: 1, date: ISODate("2000-01-04") },
    { id: 2, date: ISODate("2000-01-02") },
    { id: 2, date: ISODate("2000-01-03") },
    { id: 3, date: ISODate("2000-01-03") }
]);

以下聚合将为您提供使用$setDifference运算符实现目标的方向:

var start = new Date(2000, 0, 1);
var end = new Date(2000, 0, 2)
db.collection.aggregate([
    {
        "$match":{
            "date": {
                "$gte": start, 
                "$lte": end 
            }
        }
    },
    {
        $group: {
            _id: "$date",            
            "A": {
                "$addToSet": {
                    "$cond": [
                        { "$eq": [ "$date", start ] },
                        "$id",
                        false
                    ]
                }
            },
            "B": {
                "$addToSet": {
                    "$cond": [
                        { "$eq": [ "$date", end ] },
                        "$id",
                        false
                    ]
                }
            }
        }
    },
    { 
        "$project": {
            "A": {
                "$setDifference": [ "$A", [false] ]
            },
            "B": {
                "$setDifference": [ "$B", [false] ]
            }
        }
    },
    { 
        "$project": {
            "_id": 0,
            "date": "$_id",
            "created_set": {
                "$setDifference": [ "$B", "$A" ]
            },
            "destroyed_set": {
                "$setDifference": [ "$A", "$B" ]
            }
        }
    }
]);

<强>输出

{
    "result" : [ 
        {
            "date" : ISODate("2000-01-02T00:00:00.000Z"),
            "created_set" : [2, 1],
            "destroyed_set" : []
        }, 
        {
            "date" : ISODate("2000-01-01T00:00:00.000Z"),
            "created_set" : [],
            "destroyed_set" : [1]
        }
    ],
    "ok" : 1
}