MongoDB: Wie aktualisiere ich ein einzelnes Unterelement in einem Array, auf das der Index im Array verweist?

79

Ich versuche, ein einzelnes Unterelement zu aktualisieren, das in einem Array in einem Mongodb-Dokument enthalten ist. Ich möchte das Feld anhand seines Array-Index referenzieren (Elemente innerhalb des Arrays haben keine Felder, von denen ich garantieren kann, dass sie eindeutige Bezeichner sind). Das scheint einfach zu sein, aber ich kann die Syntax nicht herausfinden.

Folgendes möchte ich in Pseudo-Json tun.

Vor:

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

Nach:

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

Die Abfrage sollte ungefähr so ​​aussehen:

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

Das funktioniert aber nicht. Ich habe viel zu lange damit verbracht, die Mongodb-Dokumente zu durchsuchen und verschiedene Variationen dieser Syntax auszuprobieren (z. B. Verwenden $sliceusw.). Ich kann keine klare Erklärung dafür finden, wie diese Art von Update in MongoDB durchgeführt werden kann.

Abe
quelle

Antworten:

74

Wie erwartet ist die Abfrage einfach, sobald Sie wissen, wie. Hier ist die Syntax in Python:

db["my_collection"].update(
    { "_id": ObjectId(document_id) },
    { "$set": { 'documents.'+str(doc_index)+'.content' : new_content_B}}
)
Abe
quelle
13
wo ist das dokumentiert
ROROROOROROR
Dies führt dazu, dass ein gleichnamiges Objekt erstellt wird, anstatt das Array zu aktualisieren
Kisinga,
Das ist definitiv eine veraltete Antwort.
Mark Odey
48

Die Aktualisierung eines Array-Elements, auf das in Mongo Shell durch einen Index (z. B. 1) verwiesen wird, kann auch durch direkte Angabe des Indexwerts erfolgen:

db.my_collection.update(
    {_id : "document_id"},
    {$set : {"my_array.1.content" : "New content B"}}
)
Tomaskazemekas
quelle
Wie machen wir das, wenn wir den Index nicht kennen?
Muhammad Shahzad
42

Im Mongo-Stil mit dem Positionsoperator '$'. Überprüfen Sie diesen Link für Details.

db.my_collection.update(
  {_id: ObjectId(document_id), my_array.1 : 1 },
  { $set: { "my_array.$.content" : "NEW content B" } }
)
Doel
quelle
Das ist die beste Antwort!
Bogdan Kobylynskyi
7
db.my_collection.update(
  {_id: ObjectId(document_id), my_array : { ... old content A ... } },
  { $set: { "my_array.$.content" : "NEW content B" } }
)
znbwo
quelle
5

Wenn ein Array-Element aktualisiert werden muss, ohne den tatsächlichen Index zu kennen, aber eine eindeutige Kennung des Elements hat:

// 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")
        }
    }
)

Hier "bucket.commentId"ist die eindeutige Kennung eines Array-Elements.

iamcrypticcoder
quelle
In der Mongo-Shell mit findAndModify funktionieren doppelte Anführungszeichen in $setmir nicht. Ich muss einfache Anführungszeichen für das Feld verwenden.
WesternGun
4

Sie können die updateOne-Funktion von mongoDB verwenden, die den Index des Elements im Array übergibt, wenn der Schlüssel des alten Inhalts B beispielsweise "Wert" ist:

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

Der Befehl sollte folgendermaßen aussehen:

db.collection.updateOne({"_id" : "...,"},{$set: {"my_array.1.value": "NEW content B"}})
Samuel Cabral
quelle
5
Wie machen wir das, wenn wir den Index nicht kennen?
Shaharyar Kirmani
3

Eine gute Möglichkeit, dies in Javascript mit Backticks zu tun, ist:

 const index = 1;

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

Wenn ein Array-Element aktualisiert werden muss, ohne zu wissen, dass es sich um einen tatsächlichen Index handelt, der jedoch eine eindeutige Kennung des Elements aufweist

db.getCollection('profiles').update(
  {
    'userId':'4360a380-1540-45d9-b902-200f2d346263',
    'skills.name':'css'
  },
  {
      $set: {'skills.$.proficiencyLevel': 5}
  }, 
  {
      multi: true
  }
)
Amarnathrao Sulake
quelle