MongoDB 查询所有包含集合中不再存在的 id 的文档
MongoDB query all documents contains ids that does not exist anymore in the collection
我 运行 遇到了一个问题,但我还没有找到解决方案。
我有一个包含数十个文档的集合,每个文档都包含一个列表(让我们使用名称 'list' 作为该列表的键)和其他文档的 ID(它们以某种方式连接)。
集合中的一些文档已被删除,我试图找到包含集合中不再存在的文档 ID 的所有文档。
示例:
关于上面的示例:我想获取 ID 为 5e3266e9bd724a000107a902 的文档,因为它包含一个 ID 为 5e32a7f7bd724a00012c1104 的列表,该列表不再存在。
这是一个在 same 集合上利用 $lookup
的解决方案(想想“self-JOIN”):
var r = [
{_id: 0, aa: [ 10, 11, 12 ] }
,{_id: 1, aa: [ 10, 11, 12 ] }
,{_id: 2, aa: [ 20, 21, 22 ] } // 21 is on watch list...
,{_id: 3, aa: [ 21, 20, 12 ] } // this one too and 21 is in different position
,{_id: 4, aa: [ 10, 22, 12 ] }
,{_id: 5, aa: [ 10, 22, 23 ] } // this one too...
,{_id: 6, aa: [ 10, 22, 21, 23 ] } // this one has BOTH 21 and 23
,{_id: 10, X:10}
,{_id: 11, X:11}
,{_id: 12, X:12}
,{_id: 20, X:20}
,{_id: 21, X:21}
,{_id: 22, X:22}
,{_id: 23, X:23}
];
db.foo.insert(r);
// Here is the whole thing:
db.foo.aggregate([ ]);
// Delete _id 21 and 23:
db.foo.remove({_id: 21});
db.foo.remove({_id: 23});
// Double check:
c = db.foo.aggregate([ ]);
// Where does id 21 and/or 23 NOT exist anymore? Note we don't ask for 21 or 23.
// We just know we expect a query to return docs that indicate 21 and/or 23
// are no longer there:
c = db.foo.aggregate([
// NOTE! By using localField:'aa', we are asking for EACH element in the
// array to be used as a value to match to _id (in the same collection):
{$lookup: {from: 'foo', localField: 'aa', foreignField: '_id', as: 'X'}},
// Exploit "make a list of scalars from array of objects" notation by taking
// input array $X and taking the _id field out:
{$project: {X: {$setDifference: ["$aa", "$X._id"] }} },
// Keep those that match -- and protect against against empty sets
// with $ifNull to turn a null into an array of len 0:
{$match: {$expr: {$gt:[{$size: {$ifNull:['$X',[]]}}, 0]}} }
]);
{ "_id" : 2, "X" : [ 21 ] }
{ "_id" : 3, "X" : [ 21 ] }
{ "_id" : 5, "X" : [ 23 ] }
{ "_id" : 6, "X" : [ 21, 23 ] }
我 运行 遇到了一个问题,但我还没有找到解决方案。 我有一个包含数十个文档的集合,每个文档都包含一个列表(让我们使用名称 'list' 作为该列表的键)和其他文档的 ID(它们以某种方式连接)。
集合中的一些文档已被删除,我试图找到包含集合中不再存在的文档 ID 的所有文档。
示例:
关于上面的示例:我想获取 ID 为 5e3266e9bd724a000107a902 的文档,因为它包含一个 ID 为 5e32a7f7bd724a00012c1104 的列表,该列表不再存在。
这是一个在 same 集合上利用 $lookup
的解决方案(想想“self-JOIN”):
var r = [
{_id: 0, aa: [ 10, 11, 12 ] }
,{_id: 1, aa: [ 10, 11, 12 ] }
,{_id: 2, aa: [ 20, 21, 22 ] } // 21 is on watch list...
,{_id: 3, aa: [ 21, 20, 12 ] } // this one too and 21 is in different position
,{_id: 4, aa: [ 10, 22, 12 ] }
,{_id: 5, aa: [ 10, 22, 23 ] } // this one too...
,{_id: 6, aa: [ 10, 22, 21, 23 ] } // this one has BOTH 21 and 23
,{_id: 10, X:10}
,{_id: 11, X:11}
,{_id: 12, X:12}
,{_id: 20, X:20}
,{_id: 21, X:21}
,{_id: 22, X:22}
,{_id: 23, X:23}
];
db.foo.insert(r);
// Here is the whole thing:
db.foo.aggregate([ ]);
// Delete _id 21 and 23:
db.foo.remove({_id: 21});
db.foo.remove({_id: 23});
// Double check:
c = db.foo.aggregate([ ]);
// Where does id 21 and/or 23 NOT exist anymore? Note we don't ask for 21 or 23.
// We just know we expect a query to return docs that indicate 21 and/or 23
// are no longer there:
c = db.foo.aggregate([
// NOTE! By using localField:'aa', we are asking for EACH element in the
// array to be used as a value to match to _id (in the same collection):
{$lookup: {from: 'foo', localField: 'aa', foreignField: '_id', as: 'X'}},
// Exploit "make a list of scalars from array of objects" notation by taking
// input array $X and taking the _id field out:
{$project: {X: {$setDifference: ["$aa", "$X._id"] }} },
// Keep those that match -- and protect against against empty sets
// with $ifNull to turn a null into an array of len 0:
{$match: {$expr: {$gt:[{$size: {$ifNull:['$X',[]]}}, 0]}} }
]);
{ "_id" : 2, "X" : [ 21 ] }
{ "_id" : 3, "X" : [ 21 ] }
{ "_id" : 5, "X" : [ 23 ] }
{ "_id" : 6, "X" : [ 21, 23 ] }