51 votes

Mise à jour des tableaux imbriqués dans mongodb

J'ai un document dans mongodb avec 2 niveaux de profondeur imbriquée tableau d'objets que j'ai besoin de mettre à jour, quelque chose comme ceci:

{
    id: 1,
    items: [
        {
            id: 2,
            blocks: [
                {
                    id: 3
                    txt: 'hello'
                }
            ]
        }
    ] 
}

Si il n'y a qu'un seul niveau de profondeur de tableau je pouvais utiliser l'opérateur de position pour les objets de mise à jour, mais pour le deuxième niveau de la seule option que j'ai est venu est d'utiliser l'opérateur de position avec l'objet imbriqué de l'index, comme ceci:

db.objects.update({'items.id': 2}, {'$set': {'items.$.blocks.0.txt': 'hi'}})

Cette approche fonctionne, mais il semble dangereux de moi depuis que je suis en train de construire un service web et le numéro d'index doit venir de client qui peut envoyer dire 100000 comme indice et ce sera la force de mongodb pour créer un tableau avec des indices de 100000 avec la valeur null.

Existe-il d'autres façons de mettre à jour ces objets imbriqués où je peux consulter IDENTIFIANT d'objet au lieu de sa position ou peut-être les moyens de vérifier s'il est fourni, l'index est en dehors des limites avant de l'utiliser dans la requête?

30voto

Gates VP Points 26481

Voici la grande question, avez-vous besoin de tirer parti de Mongo du "addToSet" et "push"? Si vous avez vraiment l'intention de modifier simplement les différents éléments dans un tableau, alors vous devriez probablement construire ces tableaux comme des objets.

Voici comment je ferais cette structure:

{
    id: 1,
    items: 
        { 
          "2" : { "blocks" : { "3" : { txt : 'hello' } } },
          "5" : { "blocks" : { "1" : { txt : 'foo'}, "2" : { txt : 'bar'} } }
        }
}

En fait cela transforme tout à objets JSON au lieu des tableaux. Vous perdez la possibilité d'utiliser $push et $addToSet mais je pense que cela rend tout plus facile. Par exemple, votre requête devrait ressembler à ceci:

db.objects.update({'items.2': {$exists:true} }, {'$set': {'items.2.blocks.0.txt': 'hi'}})

Vous remarquerez également que j'ai viré la "Id". Lorsque vous êtes à la nidification des choses comme cela, vous pouvez généralement remplacer "ID" avec simplement l'aide de ce numéro comme un indice. "ID" concept est implicite.

3voto

Seraj Points 31

Les identifiants que vous utilisez sont des nombres linéaires et doivent provenir de quelque part comme un champ supplémentaire tel que 'max_idx' ou quelque chose de similaire. Cela signifie une recherche pour l'id, puis mettre à jour. UUID / ObjectId peut être utilisé pour les identifiants, ce qui garantit que vous pouvez également utiliser CRUD distribué.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X