963 Stimmen

Abfrage nach Dokumenten, bei denen die Feldgröße größer als 1 ist

Ich habe eine MongoDB-Sammlung mit Dokumenten im folgenden Format:

{
  "_id" : ObjectId("4e8ae86d08101908e1000001"),
  "name" : ["Name"],
  "zipcode" : ["2223"]
}
{
  "_id" : ObjectId("4e8ae86d08101908e1000002"),
  "name" : ["Another ", "Name"],
  "zipcode" : ["2224"]
}

Ich kann derzeit Dokumente abrufen, die einer bestimmten Array-Größe entsprechen:

db.accommodations.find({ name : { $size : 2 }})

Dies liefert korrekt die Dokumente mit 2 Elementen in der name Array. Ich kann jedoch nicht eine $gt alle Dokumente zurück, in denen die name Feld eine Array-Größe von mehr als 2 hat:

db.accommodations.find({ name : { $size: { $gt : 1 } }})

Wie kann ich alle Dokumente mit einer name Array mit einer Größe von mehr als eins (vorzugsweise ohne die aktuelle Datenstruktur zu ändern)?

1778voto

JohnnyHK Punkte 289697

In MongoDB 2.2+ gibt es jetzt eine effizientere Methode, dies zu tun, da Sie numerische Array-Indizes (0-basiert) in Abfrageobjektschlüsseln verwenden können.

// Find all docs that have at least two name array elements.
db.accommodations.find({'name.1': {$exists: true}})

Sie können diese Abfrage mit einem Index unterstützen, der einen partiellen Filterausdruck verwendet (erfordert 3.2+):

// index for at least two name array elements
db.accommodations.createIndex(
    {'name.1': 1},
    {partialFilterExpression: {'name.1': {$exists: true}}}
);

619voto

Andrew Orsich Punkte 51107

Aktualisierung:

Für Mongodb-Versionen 2.2+ eine effizientere Methode, dies zu tun, beschrieben von @JohnnyHK in einem anderen Antwort .


  1. 使用方法 $wo

    db.accommodations.find( { $where: "this.name.length > 1" } );

Aber...

Javascript wird langsamer ausgeführt als die nativen Operatoren, die auf dieser Seite, ist aber sehr flexibel. Siehe die Seite zur serverseitigen Verarbeitung für weitere Informationen.

  1. erstellen. extra Feld NamesArrayLength aktualisieren Sie sie mit der Länge des Namensfeldes und verwenden Sie sie dann in Abfragen:

    db.accommodations.find({"NamesArrayLength": {$gt: 1} });

Das ist eine bessere Lösung und funktioniert viel schneller (Sie können einen Index erstellen).

180voto

Tobia Punkte 16295

Ich glaube, dies ist die schnellste Abfrage, die Ihre Frage beantwortet, weil sie keine interpretierte $where Klausel:

{$nor: [
    {name: {$exists: false}},
    {name: {$size: 0}},
    {name: {$size: 1}}
]}

Es bedeutet "alle Dokumente außer denen ohne Namen (entweder nicht vorhanden oder leeres Feld) oder mit nur einem Namen".

Test:

> db.test.save({})
> db.test.save({name: []})
> db.test.save({name: ['George']})
> db.test.save({name: ['George', 'Raymond']})
> db.test.save({name: ['George', 'Raymond', 'Richard']})
> db.test.save({name: ['George', 'Raymond', 'Richard', 'Martin']})
> db.test.find({$nor: [{name: {$exists: false}}, {name: {$size: 0}}, {name: {$size: 1}}]})
{ "_id" : ObjectId("511907e3fb13145a3d2e225b"), "name" : [ "George", "Raymond" ] }
{ "_id" : ObjectId("511907e3fb13145a3d2e225c"), "name" : [ "George", "Raymond", "Richard" ] }
{ "_id" : ObjectId("511907e3fb13145a3d2e225d"), "name" : [ "George", "Raymond", "Richard", "Martin" ] }
>

95voto

one_cent_thought Punkte 869

Sie können auch Aggregate verwenden:

db.accommodations.aggregate(
[
     {$project: {_id:1, name:1, zipcode:1, 
                 size_of_name: {$size: "$name"}
                }
     },
     {$match: {"size_of_name": {$gt: 1}}}
])

// Sie fügen "size_of_name" zum Transitdokument hinzu und verwenden es, um die Größe des Namens zu filtern

92voto

s7vr Punkte 69305

Sie können verwenden $expr ( 3.6 mongo version operator ), um Aggregationsfunktionen in regulären Abfragen zu verwenden.

Vergleichen Sie query operators gegen aggregation comparison operators .

db.accommodations.find({$expr:{$gt:[{$size:"$name"}, 1]}})

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X