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

How do I compute the difference of two queries?

我有一个 MongoDB 集合,其中包含一组文档。每个文档都有一个 ISODate date 和一个整数 id(不是 _id)。如果集合中有字段值为 { id: X, date: D } 的文档,则认为 id: X exist for 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 }

我想随着时间的推移跟踪 id 的日常创建和销毁。使用上述数据,在 1/1/2000 到 1/4/2000 的日期范围内:

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

我认为解决这个问题的最好方法是一天一天地循环,看看今天和第二天之间存在什么 id,然后执行一组差异。例如,要获取在 2000 年 1 月 2 日创建和销毁的 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() 命令获取 AB 的游标,但我不知道如何在两个游标之间执行 set_difference

我的另一个选择是使用聚合管道,但我想不出如何以可以使用 $setDifference 运算符的方式来制定管道。

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

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

假设您有以下示例集合:

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
}