如何计算两个查询的差异?
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()
命令获取 A
和 B
的游标,但我不知道如何在两个游标之间执行 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
}
我有一个 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()
命令获取 A
和 B
的游标,但我不知道如何在两个游标之间执行 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
}