it-swarm.com.de

Suchen Sie in MongoDB nach Dokumenten mit Arrays, die kein Dokument mit einem bestimmten Feldwert enthalten

Ich versuche, alle Dokumente zu finden, die nicht mindestens ein Dokument mit einem bestimmten Feldwert enthalten. Zum Beispiel ist hier eine Beispielsammlung:

{  _id : 1,
  docs : [
        { foo : 1,
          bar : 2},
        { foo : 3,
          bar : 3}
         ]
},
{  _id : 2,
  docs : [
        { foo : 2,
          bar : 2},
        { foo : 3,
          bar : 3}
         ]
}

Ich möchte jeden Datensatz finden, in dem sich kein Dokument im docs-Block befindet, das nicht mindestens einen Datensatz mit foo = 1 enthält. Im obigen Beispiel sollte nur das zweite Dokument zurückgegeben werden.

Ich habe Folgendes ausprobiert, aber es wird nur angezeigt, ob es welche gibt, die nicht übereinstimmen (was Dokument 1 zurückgibt.

db.collection.find({"docs": { $not: {$elemMatch: {foo: 1 } } } })

UPDATE: Die obige Abfrage funktioniert tatsächlich. Wie so oft stimmten meine Daten nicht mit meinem Code überein.

Ich habe mir auch den $ nin-Operator angesehen, aber die Beispiele zeigen nur, wenn das Array eine Liste primitiver Werte enthält, kein zusätzliches Dokument. Wenn ich versucht habe, dies mit etwas wie dem Folgenden zu tun, sucht es nach dem GENAUEN Dokument und nicht nur nach dem gewünschten foo-Feld.

db.collection.find({"docs": { $nin: {'foo':1 } } })

Gibt es überhaupt eine Möglichkeit, dies mit den Basisoperatoren zu erreichen?

49
Scott

Mit $nin funktioniert, aber Sie haben die falsche Syntax. Es sollte sein:

db.collection.find({'docs.foo': {$nin: [1]}})
50
JohnnyHK

Verwenden Sie den Operator $ne :

db.collection.find({'docs.foo': {$ne: 1}})

Update: Ich würde davon abraten, in diesem Fall $nin Zu verwenden.

{'docs.foo': {$ne: 1}} Nimmt alle Elemente von docs und prüft für jedes von ihnen, ob das Feld foo gleich 1 ist oder nicht. Wenn eine Übereinstimmung gefunden wird, wird das Dokument aus der Ergebnisliste entfernt.

{'docs.foo': {$nin: [1]}} Nimmt alle Elemente von docs und prüft für jedes Element, ob sein Feld foo mit einem der Mitglieder des Arrays [1] Übereinstimmt. Dies ist ein kartesisches Produkt , Sie vergleichen ein Array mit einem anderen Array, jedes Element mit jedem Element. Obwohl MongoDB klug sein mag und diese Abfrage optimiert, nehme ich an, dass Sie nur $nin Verwenden, weil "es etwas mit Arrays zu tun hat". Wenn Sie jedoch verstehen, was Sie hier tun, werden Sie feststellen, dass $nin Überflüssig ist und möglicherweise eine unterdurchschnittliche Leistung aufweist.

23
aedm