MongoDB: ¿Cómo actualizo un único subelemento en una matriz, al que hace referencia el índice dentro de la matriz?


84

Estoy intentando actualizar un solo subelemento contenido dentro de una matriz en un documento mongodb. Quiero hacer referencia al campo usando su índice de matriz (los elementos dentro de la matriz no tienen ningún campo que pueda garantizar que serán identificadores únicos). Parece que esto debería ser fácil de hacer, pero no puedo entender la sintaxis.

Esto es lo que quiero hacer en pseudo-json.

Antes de:

{
  _id : ...,
  other_stuff ... ,
  my_array : [
    { ... old content A ... },
    { ... old content B ... },
    { ... old content C ... }
  ]
}

Después:

{
  _id : ...,
  other_stuff ... ,
  my_array : [
    { ... old content A ... },
    { ... NEW content B ... },
    { ... old content C ... }
  ]
}

Parece que la consulta debería ser algo como esto:

//pseudocode
db.my_collection.update(
  {_id: ObjectId(document_id), my_array.1 : 1 },
  {my_array.$.content: NEW content B }
)

Pero esto no funciona. He pasado demasiado tiempo buscando en los documentos de mongodb y probando diferentes variaciones de esta sintaxis (por ejemplo $slice, usando , etc.). No puedo encontrar una explicación clara de cómo realizar este tipo de actualización en MongoDB.

Respuestas:


76

Como era de esperar, la consulta es fácil una vez que sepa cómo. Aquí está la sintaxis, en python:

db["my_collection"].update(
    { "_id": ObjectId(document_id) },
    { "$set": { 'documents.'+str(doc_index)+'.content' : new_content_B}}
)

13
donde esta documentado?
ROROROOROROR

Esto termina creando un objeto con el mismo nombre en lugar de actualizar la matriz
Kisinga

Definitivamente es una respuesta obsoleta.
Mark Odey

49

La actualización de un elemento de matriz al que hace referencia un índice (por ejemplo, 1) en Mongo Shell también se puede realizar indicando directamente el valor del índice:

db.my_collection.update(
    {_id : "document_id"},
    {$set : {"my_array.1.content" : "New content B"}}
)

¿Cómo lo hacemos si no conocemos el índice?
Muhammad Shahzad

46

En estilo mongo, usando el operador posicional '$'. Consulte este enlace para obtener más detalles.

db.my_collection.update(
  {_id: ObjectId(document_id), my_array.1 : 1 },
  { $set: { "my_array.$.content" : "NEW content B" } }
)

¡Esa es la mejor respuesta!
Bogdan Kobylynskyi

8
db.my_collection.update(
  {_id: ObjectId(document_id), my_array : { ... old content A ... } },
  { $set: { "my_array.$.content" : "NEW content B" } }
)

5

Cuando se requiere actualizar un elemento de matriz sin saber su índice real pero con un identificador único del elemento:

// Modify a comment in a bucket
db.POST_COMMENT.update(
    {
        "_id": ObjectId("5ec424a1ed1af85a50855964"),
        "bucket.commentId": "5eaf258bb80a1f03cd97a3ad_lepf4f"
    },
    {
        $set: {
            "bucket.$.text": "Comment text changed",
            "bucket.$.createdDate": ISODate("2015-12-11T14:12:00.000+0000")
        }
    }
)

Aquí "bucket.commentId"está el identificador único de un elemento de matriz.


En el shell de Mongo con findAndModify, las comillas dobles $setno me funcionan. Tengo que usar comillas simples para el campo.
WesternGun

4

Puede usar la función updateOne de mongoDB pasando el índice del elemento en la matriz, si la clave del contenido antiguo B es "valor" por ejemplo:

[
...
"value" : "old content A"
"value" : "old content B"
"value" : "old content C"
...
]

el comando debería ser así:

db.collection.updateOne({"_id" : "...,"},{$set: {"my_array.1.value": "NEW content B"}})

5
¿Cómo lo hacemos si no conocemos el índice?
Shaharyar Kirmani

3

Una forma ordenada de hacerlo en Javascript, con comillas invertidas, es:

 const index = 1;

 ...  {   $set: { [`myArray.${index}.value`]: "new content"}  },  ...

1

Cuando se requiere actualizar un elemento de matriz sin saber que es un índice real, pero que tiene un identificador único del elemento

db.getCollection('profiles').update(
  {
    'userId':'4360a380-1540-45d9-b902-200f2d346263',
    'skills.name':'css'
  },
  {
      $set: {'skills.$.proficiencyLevel': 5}
  }, 
  {
      multi: true
  }
)
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.