Recherche de valeur de n’importe quel champ dans MongoDB sans le nommer explicitement

J’ai parcouru la documentation de MongoDB et j’ai googlé cette question mais je n’ai pas vraiment trouvé de réponse appropriée. Alors, voici ce que je recherche. Supposons que j’ai une collection avec des éléments comme celui-ci:

{ "foo" : "bar", "test" : "test", "key" : "value", } 

Ce que je voudrais réaliser, c’est de trouver un élément en recherchant dans tous les champs (peut-être à l’exception de nombreux autres ;-)). En d’autres termes: Étant donné une requête, je ne sais pas dans quel champ la requête doit être trouvée.

En pensant quelque chose comme ça

 db.things.find({_ANY_ : "bar"}) 

me donnerait l’élément d’exemple.

Merci de votre aide.

Cela n’est pas possible sans inspection individuelle des documents côté application ou via l’exécution de code côté serveur. Pensez à modifier votre schéma pour:

 {params:[{field:"foo", value:"bar"}, {field:"test", value:"test"}, {field:"key", value:"value"}]} 

Cela a évidemment des inconvénients (performance et schémas polis principalement) mais permettra ce dont vous avez besoin à travers:

 db.things.find({'params.value':"bar"}) 

Pour effectuer une recherche de texte sur tous les champs, vous devez d’abord créer un index de texte sur tous les champs.

Comme l’indique la documentation mongodb , “Pour autoriser la recherche de texte sur tous les champs avec un contenu de chaîne, utilisez le spécificateur générique ($ **) pour indexer tous les champs contenant du contenu de chaîne.”

Si vous travaillez dans le shell mongo (que vous exécutez depuis la ligne de commande en appelant «mongo»), vous pouvez le faire avec cette commande, où «collection» est le nom de la collection dans la firebase database que vous souhaitez utiliser.

db.collection.createIndex({ "$**": "text" },{ name: "TextIndex" })

le deuxième object, c’est-à-dire {name:"TextIndex"} , est optionnel … vous n’avez pas besoin de donner un nom à l’index, car il ne peut y avoir qu’un seul index de texte par collection (à la fois … vous peut supprimer des index et en créer de nouveaux si vous le souhaitez).

Une fois que vous avez créé un index de texte sur tous les champs, vous pouvez effectuer une recherche de texte simple avec l’object de requête suivant: { $text : { $search: } }

donc, si vous écrivez une fonction javascript, vous pouvez faire quelque chose comme:

var cursor = db.collection().find({ $text: { $search: } });

Pour plus d’informations sur les différentes façons de contrôler la recherche, consultez la documentation mongodb sur la recherche de texte ici

Cette réponse à une question similaire a votre solution, que je vais répéter ici pour être complet. Vous pouvez utiliser l’opérateur $where pour exécuter du code JavaScript arbitraire sur le (s) serveur (s) MongoDB, en sachant que cela sera beaucoup plus lent que tout autre type de requête. Pour votre exemple, ce serait:

 db.things.find({$where: function() { for (var key in this) { if (this[key] === "bar") { return true; } return false; } }}); 

Malheureusement, aucune des réponses précédentes n’indique que mongo peut contenir des valeurs nestedes dans des tableaux ou des objects nesteds.

C’EST LA QUESTION CORRECTE:

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

Étant donné que l’appel de typeof sur un tableau ou un object nested renverra «object», cela signifie que la requête effectuera une itération sur tous les éléments nesteds et effectuera une itération jusqu’à ce que la clé contenant la valeur soit trouvée.

Vous pouvez vérifier les réponses précédentes avec une valeur nestede et les résultats seront loin d’être souhaités.

Ssortingngifier l’object entier est beaucoup moins performant puisqu’il doit parcourir tous les secteurs de la mémoire un par un en essayant de les faire correspondre. Et crée une copie de l’object en tant que chaîne dans la mémoire RAM (les deux étant inefficaces car la requête utilise plus de mémoire vive et lente car le contexte de la fonction a déjà un object chargé)

Vous pouvez le faire avec une fonction récursive:

 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 ssortingng'); 

Pour effectuer une recherche de texte, vous devez créer des index de texte pour votre collection. Pour plus d’informations, consultez la documentation mongo: indexes text

Utiliser $ where est identique à faire un scan de table complet et ne peut pas utiliser les index. Je ne pouvais pas non plus le faire fonctionner, cependant j’ai trouvé que cela fonctionnait (il fait également l’équivalent d’une parsing de table complète):

 db.collection.find().forEach(function(doc){ for (var key in doc) { if ( /needle/.test(doc[key]) ) printjson(doc); } }); 

/needle/ est une expression régulière à trouver dans la valeur de doc[key]

 { "foo" : "bar", "test" : "test", "key" : "value", } db.collection_name.find({'foo':"bar"})