2012-03-28 4 views
2

Ich versuche eine Mongo-Abfrage zu erstellen, bei der ich Dokumente basierend auf dem Wert innerhalb eines untergeordneten Arrays auswählen kann, in dem sich die Schlüssel des eingebetteten Arrays von Dokument zu Dokument ändern.Mongo: Abfrage von Werten, die in untergeordneten Arrays verschachtelt sind, deren Schlüssel variabel sind

Im folgenden Beispiel haben wir drei Dokumentarrays. Den Namen jedes Weines zu ziehen ist trivial. Das Problem tritt auf, wenn ich die Weine auswählen möchte, die Verkostungsergebnisse größer als 20 haben. Das Problem ist, dass ich den Namen des Fluges nicht kenne, wenn ich die Abfrage führe; es könnte alles sein.

Daher kann ich nicht nur gegen die Werte des eingebetteten Array überprüfen.

Ich habe darüber nachgedacht, so etwas wie

$ary_query = array('tasting_results.*' => '$gt: 20');

aber anscheinend Platzhalter funktionieren nicht in Mongo (zumindest nicht so). Irgendwelche Ideen?

Hier ist der Beispiel-Arrays:

ary_wines = array(
"name" => "Ripple", 
"year" => "2013", 
"style" => "cabernet", 
"size" => "750ml", 
"tasting_results" => array (
    "flight_42" => 12, 
    "flight_2" => 18, 
    "flight_33" => 7 
    ) 
) 

ary_wines = array(
"name" => "Riunite", 
"year" => "2012", 
"style" => "White Zinfandel", 
"size" => "1.5L", 
"tasting_score" => array (
    "flight_6" => 14, 
    "flight_54" => 21, 
    "flight_98" => 3 
    ) 
) 

ary_wines = array(
"name" => "Maneschewitz", 
"year" => "2012", 
"style" => "Grape Juice", 
"size" => "500ml", 
"tasting_score" => array (
    "flight_7" => 12, 
    "flight_41" => 26, 
    "flight_9" => 3 
    ) 
) 

Antwort

2

Nun, man kann technisch mit der $where Klausel eine Tabelle Scan-Stil Abfrage tun:

db.wines.find({$where: function() { 
    var keys = Object.keys(this.tasting_score); 
    keys.forEach(function(key) { 
     if(this.tasting_score[key] > 20) { return true; } 
    }); 
    return false; 
}); 

Aber, ich flehe Sie an, ist dies ein schrecklich Idee, und es wäre viel besser, Ihre Daten in der Datenbank in einer indexierbaren Weise, wo Sie Standard-Abfrage-Methoden verwenden können. Genau wie Sie dies tun sollten, hängt davon ab, wie Ihre Anwendung die Daten manipulieren wird, aber zumindest können Sie beim Einfügen vorprozessieren und einen maxTastingScore Parameter in Ihrem Objekt haben, um abzufragen, ob dies die einzige Abfrage ist, die nicht funktioniert. t passen Sie Ihre Datenstruktur an.

+0

Dank David, ja, ich dachte an etwas so, aber dann verworfen es, weil es scheint, als würde es nicht gut skalieren. Also, ich denke, ich muss die Art und Weise ändern, wie ich die Dokumente erstelle, ist im Grunde das, was du sagst. – DenverMatt

+1

Ja, MongoDB gibt Ihnen einen Leistungsschub * wenn * Sie die richtige Dokumentstruktur finden können. Wenn es keine gute Struktur gibt, kann es sinnvoller sein, mit PostgreSQL oder am anderen Ende mit Neo4j zu gehen. Aber nach einigem Nachdenken kannst du es vielleicht mit einer Struktur wie: "tasting_score: [{flight_num: 7, score: 20}, {flight_num: 18, score: 7}, ...]" machen. Dann können Sie '' db.wines.find ({"tasting_score.score": {$ gt: 20}}) ''. Es hängt natürlich davon ab, welche anderen Abfragen Sie durchführen möchten. –

0

Können Sie versuchen, Elemente einzeln zu filtern und so etwas wie ein OR zu tun?

Ich habe eine Struktur entlang der Linien von

"entities": { 
    "user_mentions": { 
    "0": { 
     "indices": { 
      "0": 0, 
      "1": 10 
     } 
    }, 
    "1": { 
     "indices": { 
      "0": 41, 
      "1": 51 
     } 
    } 
} 

Die Abfrage kann wie so aussieht:

{ 
"entities.user_mentions.indices.0": {$gt:10}, 
"entities.user_mentions.indices.1": {$gt:20} 
} 

Auch finden MongoDB wildcard in the key of a query

Verwandte Themen