find没有邀请任何用户的用户

我想查找那些没有通过单个查询邀请任何用户的用户(使用聚合)。

例如:我有4个用户在数据库

{ "_id" : ObjectId("581a18d41b6c5c752f11c87a"), "name": "aaa", "invitedBy": ObjectId("5808f53d28c14ee470856d8b") }, { "_id" : ObjectId("581a1a671b6c5c752f11c87b"), "name": "bbb", "invitedBy": ObjectId("581a18d41b6c5c752f11c87a") }, { "_id" : ObjectId("581a1a671b6c5c752f11c87c"), "name": "ccc", "invitedBy": ObjectId("581a18d41b6c5c752f11c87a"), }, { "_id" : ObjectId("581a1a671b6c5c752f11c87d"), "name": "ddd", "invitedBy": ObjectId("581a1a671b6c5c752f11c87b"), } 

这里

1- aaa邀请bbb和ccc用户

2- BBB邀请DDD用户

3-但ccc和ddd用户没有邀请任何一个

所以我想图片cccddd用户

如果可以使用聚合,会更好,因为我需要对所选数据执行一些操作。

您可以使用$lookup运算符对集合本身执行左连接。

没有发送邀请的用户是空邀请数组的用户。 要仅检索这些用户,只需使用$exists操作符和数字数组索引来过滤$match阶段中的文档即可。

 db.users.aggregate( [ { "$lookup": { "from": "users", "localField": "_id", "foreignField": "invitedBy", "as": "invitation" }}, { "$match": { "invitation.0": { "$exists": false } } } ] ) 

这产生:

 { "_id" : ObjectId("581a1a671b6c5c752f11c87c"), "name" : "ccc", "invitedBy" : ObjectId("581a18d41b6c5c752f11c87a"), "invitation" : [ ] } { "_id" : ObjectId("581a1a671b6c5c752f11c87d"), "name" : "ddd", "invitedBy" : ObjectId("581a1a671b6c5c752f11c87b"), "invitation" : [ ] } 

还有另一种方法来做同样的事情。 但是这种方法可能最终比@ Styvane的答案效率低。 这应该工作,如果有较less的元素。

 [ {$group: {_id: null, senders: {$addToSet: '$invitedBy'}, everyone: {$addToSet: '$_id'}}}, {$project: {_id: 0, res: {$setDifference: ['$everyone', '$senders']}}} ] 

如果需要其他信息,也可以获得(抱歉,但在这里变得有点脏)

 [ {$group: {_id: null, senders: {$addToSet: '$invitedBy'}, everyone: {$addToSet: {id: '$_id', name: '$name'}}}}, {$project: {_id: 0, everyone: 1, res: {$setDifference: ['$everyone.id', '$senders']}}}, {$unwind: '$everyone'}, {$unwind: '$res'}, {$project: {flag: {$eq: ['$everyone.id', '$res']}, everyone: 1}}, {$match: {flag: true}} ]