J'ai posé cette question en tant que commentaire sur ne autre question, et j'ai également posté une question sur mongodb-user. Jusqu'à présent, je n'ai pas répondu. Je me pose donc une question distincte.
documentation indique:
Si le champ contient un tableau, l'opérateur $ in sélectionne les documents dont le champ contient un tableau qui contient au moins un élément qui correspond à une valeur du tableau spécifié (par exemple, etc.)
J'utilise:
mongod --version:
db version v2.2.2, pdfile version 4.5
Thu May 30 12:19:12 git version: d1b43b61a5308c4ad0679d34b262c5af9d664267
mongo --version:
MongoDB Shell version: 2.0.4
Dans MongoDB Shell:
db.nested.insert({'level1': {'level2': [['item00', 'item01'], ['item10', 'item11']]}})
Voici une liste de requêtes qui devraient fonctionner selon la documentation et les résultats qu'elles produisent:
Pourquoi ça ne marche pas?
> db.nested.findOne({'level1.level2.0': 'item00'})
null
Pourquoi ai-je besoin de $ all?
> db.nested.findOne({'level1.level2.0': {'$all': ['item00']}})
{
"_id" : ObjectId("51a7a4c0909dfd8872f52ed7"),
"level1" : {
"level2" : [
[
"item00",
"item01"
],
[
"item10",
"item11"
]
]
}
}
Au moins l'un des éléments suivants devrait fonctionner, non?
> db.nested.findOne({'level1.level2.0': {'$in': ['item00']}})
null
> db.nested.findOne({'level1.level2': {'$in': ['item00']}})
null
Des idées? Nous envisageons d'abandonner MongoDB si la syntaxe de requête ne fonctionne pas comme annoncé.
Merci!
Utilisez imbriqué elemMatch
pour rechercher des niveaux imbriqués dans des tableaux.
Après avoir exécuté quelques requêtes, je suis arrivé à la conclusion que $ in ne fonctionne pas pour un tableau de tableaux.
Vous pouvez utiliser $elemMatch
à la place et cela fonctionnera, mais il est frustrant que la documentation de MongoDB ne le prévienne pas.
J'ai créé ce document:
{
"_id": "51cb12857124a215940cf2d4",
"level1": [
[
"item00",
"item01"
],
[
"item10",
"item11"
]
],
"items": [
"item20",
"item21"
]
}
Notez que le champ "items" est un tableau de chaînes et cette requête fonctionne parfaitement:
db.nested.findOne({"items":{"$in":["item20"]} })
Maintenant, "level1.0" est également un tableau de chaînes, la seule différence est qu'il se trouve dans un autre tableau. Cette requête devrait fonctionner mais n'est pas:
db.nested.findOne({"level1.0":{"$in":["item00"]} })
La seule façon d'obtenir le résultat est d'utiliser $ elemMatch:
db.nested.findOne({"level1":{"$elemMatch":{"$in":['item00']}} })
Alors $elemMatch
résout le problème, mais la vraie solution est de mettre à jour la documentation de MongoDB pour indiquer que $in
ne fonctionne pas pour les tableaux de tableaux. Vous devriez peut-être soumettre une demande à 10gen.
Réponse courte: $ in est pour un champ à valeur unique et $ all est pour les tableaux.
Premièrement, db.nested.findOne({'level1.level2.0': 'item00'})
ne fonctionne pas car level1.level2.0 contient un tableau et vous essayez de le comparer avec une seule valeur.
Maintenant, db.nested.findOne({'level1.level2.0': {'$in': ['item00']}})
ne fonctionne pas non plus pour une raison similaire. $ in sert à comparer un champ avec une seule valeur (vous avez un tableau) avec plusieurs valeurs dans un tableau (spécifié dans la requête). $ in dit: donnez-moi les documents qui ont ce champ dont la valeur est incluse dans ce tableau.
$ all fonctionne parce qu'il dit: donnez-moi les documents qui ont ce champ avec plusieurs valeurs et toutes les valeurs de ce tableau (dans la requête) sont incluses dans ce champ. (édité)
Cela peut être difficile à obtenir, mais regardez ce que la documentation dit pour chacun:
$ all sélectionne les documents où le champ contient un tableau et contient tous les éléments
(e.g. <value>, <value1>, etc.
) dans le tableau.$ in sélectionne les documents où la valeur du champ est égale à toute valeur dans le tableau spécifié (
e.g. <value1>, <value2>, etc.
)
J'espère que ça aide