2016-11-16 3 views
5

Ich möchte die Benutzer finden, die keine Benutzer von einer einzigen Abfrage eingeladen hat (Aggregat verwendet wird).Suche Benutzer, die jeder Benutzer nicht eingeladen hat

zum Beispiel: Ich habe 4-Benutzer in DB

{ 
    "_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"), 
} 

Hier

1- aaa bbb und ccc Benutzer

2- bbb eingeladen ddd Benutzer eingeladen

3 - aber ccc und ddd Benutzer nicht ein

eingeladen

so möchte ich mit Aggregat ccc und ddd Benutzer

es wäre besser, wenn Dose pic, weil ich auf ausgewählte Daten eine Operation durchführen müssen.

+0

Was ist Ihre MongoDB-Version? – styvane

+0

MongoDB-Version ist 3.2 @Styvane –

+0

@ 4J41 Bitte benutzen Sie nicht die [ 'mongodb-aggregation' tag] (http://meta.stackoverflow.com/questions/337096/let-burninate-mongodb-aggregation). – styvane

Antwort

5

können Sie den $lookup Operator links ausführen kommen die Sammlung selbst.

Die Benutzer, die keine Einladung gesendet haben sind diejenigen mit leeren Einladung Array. Um nur diese Benutzer abzurufen, filtern Sie einfach die Dokumente in einer $match-Phase mit dem Operator $exists und numerischer Array-Indexierung.

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

, die ergibt:

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

dank @Styvane –

1

Es ist eine weitere Methode, das gleiche zu tun. Aber diese Methode könnte weniger effizient sein als die Antwort von @ Styvane. Dies sollte funktionieren, wenn es weniger Elemente gibt.

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

Bei anderen Informationen benötigt werden, dass auch (sorry, aber es wird hier etwas schmutzig) erhalten werden kann

[ 
    {$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}} 
] 
+0

Was passiert, wenn benötigt OP alle Felder in den Dokumenten abrufen nicht nur das '_id' Feld? – styvane

+0

@Styvane für diesen Fall aktualisiert. – hyades

Verwandte Themen