Ich habe die MongoDB-Dokumentation durchgesehen und diese Frage gegoogelt, konnte aber keine passende Antwort finden. Also, hier ist was ich suche. Angenommen, ich habe eine Sammlung mit Elementen wie diesen:
{
"foo" : "bar",
"test" : "test",
"key" : "value",
}
Was ich erreichen möchte, ist ein Element zu finden, indem ich in allen (vielleicht bis auf endlich viele ;-)) Feldern suche. Mit anderen Worten: Bei einer Abfrage weiß ich NICHT, in welchem Feld die Abfrage gefunden werden soll.
In meinem Denken so etwas
db.things.find({_ANY_ : "bar"})
würde mir das Beispielelement geben.
Danke für deine Hilfe.
Antworten:
Um eine Textsuche für alle Felder durchzuführen, müssen Sie zuerst einen Textindex für alle Felder erstellen.
Wie in der Mongodb-Dokumentation angegeben: "Um die Textsuche in allen Feldern mit Zeichenfolgeninhalt zu ermöglichen, verwenden Sie den Platzhalterbezeichner ($ **), um alle Felder zu indizieren, die Zeichenfolgeninhalte enthalten."
Wenn Sie in der Mongo-Shell arbeiten (die Sie über die Befehlszeile ausführen, indem Sie 'mongo' aufrufen), können Sie dies mit diesem Befehl tun, wobei 'collection' der Name der Sammlung in der Datenbank ist, die Sie verwenden möchten.
db.collection.createIndex({ "$**": "text" },{ name: "TextIndex" })
Das zweite Objekt
{name:"TextIndex"}
ist optional. Sie müssen dem Index keinen Namen geben, da es nur einen einzigen Textindex pro Sammlung geben kann (gleichzeitig ... können Sie Indizes löschen und neue erstellen falls Sie es wollen).Nachdem Sie einen Textindex für alle Felder erstellt haben, können Sie eine einfache Textsuche mit dem folgenden Abfrageobjekt durchführen:
{ $text : { $search: <your string> } }
Wenn Sie also eine Javascript-Funktion schreiben, können Sie Folgendes tun:
var cursor = db.collection(<collection_name>).find({ $text: { $search: <your string> } });
Weitere Informationen zu den verschiedenen Möglichkeiten zur Steuerung der Suche finden Sie in der Mongodb-Dokumentation zur Textsuche hier
quelle
Diese Antwort auf eine ähnliche Frage hat Ihre Lösung, die ich hier der Vollständigkeit halber wiederholen werde. Sie können den
$where
Operator verwenden, um beliebiges JavaScript auf den MongoDB-Servern auszuführen, mit der Einschränkung, dass dies viel langsamer ist als bei fast jeder anderen Art von Abfrage. Für Ihr Beispiel wäre es:db.things.find({$where: function() { for (var key in this) { if (this[key] === "bar") { return true; } } return false; }});
quelle
return false;
sollte eine Klammer weiter unten seinDies ist nicht möglich, ohne Dokumente auf App-Seite oder durch serverseitige Codeausführung einzeln zu überprüfen. Ändern Sie Ihr Schema in:
{params:[{field:"foo", value:"bar"}, {field:"test", value:"test"}, {field:"key", value:"value"}]}
Dies hat natürlich einige Nachteile (Leistung und meistens verschmutztes Schema), lässt aber zu, was Sie brauchen:
db.things.find({'params.value':"bar"})
quelle
Leider geht keine der vorherigen Antworten auf die Tatsache ein, dass Mongo verschachtelte Werte in Arrays oder verschachtelten Objekten enthalten kann.
DAS IST DIE RICHTIGE FRAGE:
{$where: function() { var deepIterate = function (obj, value) { for (var field in obj) { if (obj[field] == value){ return true; } var found = false; if ( typeof obj[field] === 'object') { found = deepIterate(obj[field], value) if (found) { return true; } } } return false; }; return deepIterate(this, "573c79aef4ef4b9a9523028f") }}
Da der Aufruf von typeof für ein Array oder ein verschachteltes Objekt 'object' zurückgibt, bedeutet dies, dass die Abfrage alle verschachtelten Elemente durchläuft und dann alle durchläuft, bis der Schlüssel mit dem Wert gefunden wird.
Sie können frühere Antworten mit einem verschachtelten Wert überprüfen, und die Ergebnisse sind bei weitem nicht erwünscht.
Das Stringisieren des gesamten Objekts ist weitaus weniger performant, da es alle Speichersektoren nacheinander durchlaufen muss, um sie abzugleichen. Und erstellt eine Kopie des Objekts als Zeichenfolge im RAM-Speicher (sowohl ineffizient, da die Abfrage mehr RAM verwendet, als auch langsam, da der Funktionskontext bereits ein geladenes Objekt enthält).
quelle
Sie können dies mit einer rekursiven Funktion tun:
var recursiveSearch = function(query) { db.test_insert.find().forEach(function(items) { var i = 0; var recursiveFunc = function(itemsArray, itemKey) { var itemValue = itemsArray[itemKey]; if(itemValue === query) { printjson(items); } if(typeof itemValue === "object") { Object.keys(itemValue).forEach(function(itemValueKey) { recursiveFunc(itemValue, itemValueKey); }); } }; Object.keys(items).forEach(function(item){ recursiveFunc(items, item); }); }); }; recursiveSearch('your string');
quelle
Die Verwendung von $ where entspricht der Durchführung eines vollständigen Tabellenscans und kann die Indizes nicht verwenden. Ich konnte es auch nicht zum Laufen bringen, fand es jedoch funktionierend (es entspricht auch einem vollständigen Tabellenscan):
db.collection.find().forEach(function(doc){ for (var key in doc) { if ( /needle/.test(doc[key]) ) printjson(doc); } });
wo
/needle/
ist ein regulärer Ausdruck im Wert von zu findendoc[key]
quelle
Um eine Textsuche durchzuführen, müssen Sie Textindizes für Ihre Sammlung erstellen. Weitere Informationen finden Sie in der Mongo-Dokumentation: Indiziert Text
quelle
{ "foo" : "bar", "test" : "test", "key" : "value", } db.collection_name.find({'foo':"bar"})
quelle