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.

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

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

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

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

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.


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

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"}  },  ...

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
  }
)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.