2

我有一个包含一组文档的 MongoDB 集合。每个文档都有一个 ISODatedate和一个整数id(不是_id)。如果集合中存在具有字段值的文档,则称id: X存在。因此,例如:date: D{ 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 }

我想id随着时间的推移跟踪 s,因为它们每天被创建和销毁。使用上述数据,在 2000 年 1 月 1 日至 2000 年 1 月 4 日的日期范围内:

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()命令来获取Aand的游标B,但我不知道如何set_difference在两个游标之间执行。

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

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

4

2 回答 2

2
db.mystuff.aggregate([
    {$group: {_id: '$id', created: {$first: '$date'}, destroyed: {$last: '$date'}}}
])
于 2015-04-15T21:47:01.247 回答
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
}
于 2015-04-15T21:50:50.940 回答