Mise à jour d'un Tableau Imbriqué avec MongoDB
Je suis en train de mettre à jour une valeur dans le tableau imbriqué, mais ne peut pas le faire fonctionner.
Mon objet, c'est comme cela
{
"_id": {
"$oid": "1"
},
"array1": [
{
"_id": "12",
"array2": [
{
"_id": "123",
"answeredBy": [],
},
{
"_id": "124",
"answeredBy": [],
}
],
}
]
}
J'ai besoin de pousser un valeur "answeredBy" array.
Dans l'exemple ci-dessous, j'ai essayé de pousser le "succès" de la chaîne de la "answeredBy" tableau de la "123 _id" objet, mais il ne fonctionne pas.
callback = function(err,value){
if(err){
res.send(err);
}else{
res.send(value);
}
};
conditions = {
"_id": 1,
"array1._id": 12,
"array2._id": 123
};
updates = {
$push: {
"array2.$.answeredBy": "success"
}
};
options = {
upsert: true
};
Model.update(conditions, updates, options, callback);
J'ai trouvé ce lien, mais sa réponse ne dit que je devrais utiliser l'objet comme la structure au lieu de la matrice. Ce ne peut pas être appliqué dans ma situation. J'ai vraiment besoin de mon objet imbriqué dans des tableaux
Ce serait formidable si vous pouvez m'aider ici. J'ai passé des heures à le comprendre.
Vous en remercie d'avance!
OriginalL'auteur masanorinyo | 2014-05-10
Vous devez vous connecter pour publier un commentaire.
Portée générale et Explication
Il y a quelques choses de mal avec ce que vous faites ici. Tout d'abord vos conditions de la requête. Vous faites référence à plusieurs
_id
valeurs où vous ne devez pas, et au moins un de ce qui n'est pas sur le niveau supérieur.Afin d'obtenir dans une "niche" de la valeur et aussi en supposant que
_id
valeur est unique et ne semble pas dans tout autre document, vous le formulaire de requête devrait ressembler à ceci:Maintenant qui fonctionne réellement, mais c'est vraiment seulement un coup de chance qu'il n'qu'il y a de très bonnes raisons pour lesquelles il ne devrait pas travailler pour vous.
La lecture importante est dans la documentation officielle pour la position
$
opérateur sous le thème de "Tableaux Imbriqués". Ce qui c'est dit:À ce que cela signifie, c'est l'élément qui va être appariés et retour dans la position de l'espace réservé est la valeur de l'indice de la première ensemble correspondant. Cela signifie dans votre cas, la correspondance de l'index sur le "haut" niveau de tableau.
Donc, si vous regardez la requête de la notation, comme indiqué, nous avons "codé en dur" le première ( ou indice 0 ) position dans la pile de niveau supérieur, et il se trouve que l'élément correspondant dans "tableau2" est aussi le zéro de l'entrée d'index.
Pour démontrer cela, vous pouvez modifier la mise en correspondance
_id
valeur "124" et le résultat sera$push
une nouvelle entrée sur l'élément avec_id
"123", comme ils sont tous les deux dans le zéro de l'entrée d'index de "tableau1" et c'est la valeur retournée à l'espace réservé.De sorte que c'est le problème général avec l'imbrication de tableaux. Vous pouvez supprimer l'un des niveaux et vous seriez encore capable de
$push
au bon élément dans votre "top" de tableau, mais il y aurait encore plusieurs niveaux.Essayez d'éviter l'imbrication de tableaux que vous serez confronté à des problèmes de mise à jour comme c'est indiqué.
Le cas général est de "aplatir" les choses que vous "pensez" sont des "niveaux" et fait faire des thèses "attributs" sur le dernier détail d'articles. Par exemple, le "aplatie" la forme de la structure en question doit être quelque chose comme:
Ou même lors de l'acceptation de l'intérieur de la matrice est
$push
seulement, et jamais mis à jour:Qui à la fois se prêtent à des mises à jour atomiques dans le champ d'application de la position
$
de l'opérateurMongoDB 3.6 et au-Dessus de
De MongoDB 3.6 il y a des nouvelles fonctionnalités disponibles pour travailler avec des tableaux imbriqués. Il utilise la position filtrée
$[<identificateur>]
syntaxe, afin de correspondre à des éléments particuliers et appliquer des conditions différentes à traversarrayFilters
dans l'instruction de mise à jour:La
"arrayFilters"
comme passé aux options de.mise à jour()
ou même.updateOne()
,.updateMany()
,.findOneAndUpdate()
ou.bulkWrite()
méthode spécifie les conditions pour correspondre à l'identifiant donné dans l'instruction de mise à jour. Tous les éléments qui correspondent à la condition sera mis à jour.Parce que la structure est "imbriqué", nous utilisons en fait "plusieurs filtres" comme c'est spécifié avec un "tableau" de la définition de filtre comme illustré. La mention "identifiant" est utilisé dans la correspondance contre la position filtrée
$[<identificateur>]
syntaxe effectivement utilisés dans la mise à jour du bloc de l'instruction. Dans ce casinner
etouter
sont les identifiants utilisés pour chaque condition, comme spécifié avec la imbriquée de la chaîne.Cette nouvelle extension fait la mise à jour du tableau imbriqué contenu possible, mais il n'aide pas réellement à la pratique de "l'interrogation" de telles données, de sorte que les mêmes restrictions s'appliquent comme expliqué précédemment.
Vous généralement vraiment la "moyenne" pour exprimer "attributs", même si votre cerveau pense d'abord "nidification", c'est juste généralement une réaction à la façon dont vous croyez que le "précédent relationnel pièces" venir ensemble. En réalité, vous avez vraiment besoin de plus de dénormalisation.
Voir aussi Comment mettre à Jour Plusieurs Éléments de Tableau dans mongodb, puisque ces nouvelles mise à jour en effet, les opérateurs de correspondance et de la mise à jour "de plusieurs éléments du tableau" plutôt que de simplement le première, qui a été l'action précédente de la position des mises à jour.
Voir aussi
de position de tous les $[]
qui a également des mises à jour "de plusieurs éléments du tableau", mais sans l'appliquer à certaines conditions et s'applique à tous éléments du tableau où c'est l'action souhaitée.OriginalL'auteur Neil Lunn
Je sais que c'est une très vieille question, mais j'ai juste eu du mal avec ce problème moi-même, et trouvé, ce que je crois être, une meilleure réponse.
Une façon de résoudre ce problème est d'utiliser
Sous-Documents
. Cela se fait par l'imbrication des schémas dans des schémasDe cette façon, l'objet ressemble à l'un de vous montrer, mais maintenant, chaque tableau sont remplis avec des sous-documents. Cela permet de mettre les points sur votre chemin dans le sous-document que vous voulez. Au lieu d'utiliser un
.update
vous utilisez ensuite un.find
ou.findOne
pour obtenir le document que vous souhaitez mettre à jour.N'avez pas utilisé le
.push(
) la fonction de cette façon, moi-même, de sorte que la syntaxe peut-être pas le droit, mais j'ai utilisé les deux.set()
et.remove()
, et les deux fonctionne parfaitement bien.OriginalL'auteur Jesper Nielsen