Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update embedded document?

How to update the text of second comment to "new content"

{
  name: 'Me',
  comments: [{
        "author": "Joe S.",
        "text": "I'm Thirsty"
    },
    {
        "author": "Adder K.",
        "text":  "old content"
    }]
}
like image 641
Alex Luya Avatar asked Jun 16 '13 12:06

Alex Luya


People also ask

How do I update an embedded file in MongoDB?

Update Documents in an ArrayThe positional $ operator facilitates updates to arrays that contain embedded documents. Use the positional $ operator to access the fields in the embedded documents with the dot notation on the $ operator.

How do you update an entire document?

Update all fields in a documentPress Ctrl + A. Press F9. If your document has tables with fields or formulas, you might need to select each table separately and press F9.

How do I update an element in MongoDB?

To update a set of elements matching certain filters, we must use the filtered positional operator $[<identifier>] where <identifier> is a placeholder for a value that represents a single element of the array. We must then use the third parameter (options) of the updateMany method to specify a set of arrayFilters .

How do I update a nested array in MongoDB?

Update Nested Arrays in Conjunction with $[]The $[<identifier>] filtered positional operator, in conjunction with the $[] all positional operator, can be used to update nested arrays. The following updates the values that are greater than or equal to 8 in the nested grades.


2 Answers

Updating the embedded array basically involves two steps:

1. You create a modified version of the whole array. There are multiple operations that you can use to modify an array, and they are listed here: http://www.rethinkdb.com/api/#js:document_manipulation-insert_at

In your example, if you know that the document that you want to update is the second element of the array, you would write something like

oldArray.changeAt(1, oldArray.nth(1).merge({text: "new content"}))

to generate the new array. 1 here is the index of the second element, as indexes start with 0. If you do not know the index, you can use the indexesOf function to search for a specific entry in the array. Multiple things are happening here: changeAt replaces an element of the array. Here, the element at index 1 is replaced by the result of oldArray.nth(1).merge({text: "new content"}). In that value, we first pick the element that we want to base our new element from, by using oldArray.nth(1). This gives us the JSON object

{
    "author": "Adder K.",
    "text":  "old content"
}

By using merge, we can replace the text field of this object by the new value.

2. Now that we can construct the new object, we still have to actually store it in the original row. For this, we use update and just set the "comments" field to the new array. We can access the value of the old array in the row through the ReQL r.row variable. Overall, the query will look as follows:

r.table(...).get(...).update({
    comments: r.row('comments').changeAt(1,
      r.row('comments').nth(1).merge({text: "new content"}))
  }).run(conn, callback)
like image 57
Daniel Mewes Avatar answered Oct 09 '22 15:10

Daniel Mewes


Daniel's solution is correct. However, there are several open issues on Github for planned enhancements, including:

  • generic object and array modification (https://github.com/rethinkdb/rethinkdb/issues/895)

  • being able to specify optional arguments for merge and update (https://github.com/rethinkdb/rethinkdb/issues/872)

  • being able to specify a conflict resolution function for merge (https://github.com/rethinkdb/rethinkdb/issues/873)

...among other related issues. Until those are introduced into ReQL (particularly #895), Daniel's approach is the correct one.

like image 28
Michael Glukhovsky Avatar answered Oct 09 '22 15:10

Michael Glukhovsky