3

Please share your experience with partial updating of JSON document.At now I'm storing my JSON documents in MongoDB which looks like the following:

{
  id: ObjectId(507f191e810c19729de860ea),
  title: 'Sterling Archer',    
  comments: [
    {text: 'Comment text', tags: ['tag1', 'tag2', 'tag3']},
    {text: 'Comment test', tags: ['tag2', 'tag5']}
  ]  
}

I need to frequently update my documents by using rfc6902 specification. Now, I do it not optimized way that looks the following (I use nodejs/express/mongoose and fast-json-patch module in this example):

var jsonpatch = require('fast-json-patch');

app.patch('/document/:id', function (req, res, next) {
   var document_id = req.params.id;

   // req.body.patch: { "op": "add", "path": "/comments/2", "value":  {text: 'Comment test3', tags: ['tag4']}" }
   var patches = req.body.patch; 

   // find document
   Document.findById(document_id, function (err, document) {
       // Applying patches
       jsonpatch.apply(document, patches);

       // Update whole document in MongoDB
       Document.update({_id: document_id}, document, function (err) {
           return res.status(200).send(); 
       });
   });
});

This is not optimize approach to patch documents due two queries in MongoDB and replacing whole document. So I'm looking for optimized approach and want to try RethinkDB for this task. Can you help me to inspect possibility of atomic document updating by using single query with RethinkDB? Or should I looks for another way of resolving my problem?

Please share your experience with partial updating of JSON document.

Community
  • 1
  • 1
Erik
  • 14,060
  • 49
  • 132
  • 218

1 Answers1

6

You just need one query in RethinkDB. Suppose you want to update the document whose id is 1 with the values {foo: 1, bar: 2}, and increment the field "count", you would do

r.table("data").get(1).update(function(doc) {
    return doc.merge({foo: 1, bar:2, count: doc("count").add(1) })
})

While this update requires a unique query, the whole document will be updated. If you have big documents, you can split them in multiple tables and perform joins later to retrieve the data. You may be interested in reading this article about data modeling: http://www.rethinkdb.com/docs/data-modeling/

neumino
  • 4,342
  • 1
  • 18
  • 17
  • Thanks for the reply. Unfortunately I can't split document in multiple tables. Don't RethinkDB like big nested JSON documents? – Erik Sep 24 '14 at 18:08
  • It depends what you call big and your workload. That being said, it should work fine. RethinkDB is especially efficient on SSD. But I guess the only real answer is to try your workload? – neumino Sep 24 '14 at 18:18
  • Thanks. Do you have experience with partial JSON in your projects? – Erik Sep 24 '14 at 19:55
  • (Note: I'm an engineer at RethinkDB). As far as I know, almost everyone does partial update with RethinkDB -- because it's more efficient, and it's what we are used to (it's similar to SQL UPDATE statement). On a personal note, I use it on some personal projects (like to increment stats for logs), and it works like a charm. – neumino Sep 24 '14 at 21:46
  • Thanks for the reply. Your code snippet provided is looks good I'l try to use this one but I don't understand how could I build query for `move` patch: `[{ "op": "move", "from": "/foo/waldo", "path": "/qux/thud" }]`. Can you provide code example for RethingDB please? – Erik Sep 25 '14 at 03:45
  • r.table("data").get("idValue").merge({"/qux/thud": r.row("/foo/waldo")}).without("/foo/waldo") – neumino Sep 25 '14 at 17:17
  • @neumino your comment assumes "/foo/waldo" is the key but it's not how it works in JSONPatch. It's a JSON pointer (rfc6901) to `waldo` in `{ foo: { waldo: 'value' }}`. Can RethinkDB handle that? – Matt Harrison Mar 12 '16 at 12:37