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 ] }