简体   繁体   中英

Rethinkdb append to array if exists

In RethinkDB, I have a table authors with the following layout:

{
  id: 12,
  videos: [1,2,3]
}

Now I get new authors with objects like this:

{
  id: 12,
  videos: [4,5]
}

If the author now already exists, I want to append the new videos 4 and 5 to the list of videos. If author not exists, just insert the document like it is. My approach was the following, but it didn't work.

r.table('authors').getAll(4, 3, 2, 1, {index: 'id'})
    .replace(function(author, index) {
        return r.branch(
            author.eq(null),
            {
                id: index,
                videos: [1,2,3]
            },
            author
        );
    })

-> Response:

{
    "deleted": 0 ,
    "errors": 3 ,
    "first_error":  "Expected 2 arguments but found 1." ,
    "inserted": 0 ,
    "replaced": 0 ,
    "skipped": 0 ,
    "unchanged": 0
}

Thanks!

Your logic is very good. It is just some syntax issue.

Given an author, if the author isn't existed, insert it, otherwise, append the video array, here is what I think of, using your logic:

var author = {
    id: 12,
  videos: [9, 10]
};

r.table('authors').insert(author).do(
    function (doc) {
        return r.branch(doc('inserted').ne(0),
          r.expr({inserted: 1}),
          r.table('authors').get(author["id"]).update(function(doc) {
            return {videos: doc('videos').union(author["videos"])}
          })
        )
    }
)

If the insert is sucesfully, it means we have no document with the same id , we don't have to do anything. Otherwise, we will update the document and append the videos into it.

To updare an array of multiple author, we can use foreach and expr to turn array into ReQL object. However, in this case, we use bracket to get field instead of using [] as in JavaScript object

var authors = [{
    id: 12,
    videos: [90, 91]
},{
    id: 14,
    videos: [1, 2]
}];

r.expr(authors).forEach(function(author) {

  return r.table('authors').insert(author).do(
    function (doc) {
        return r.branch(doc('inserted').ne(0),
          r.expr({inserted: 1}),
          r.table('authors').get(author("id")).update(function(doc) {
            return {videos: doc('videos').union(author("videos"))}
          })
        )
    }
  )

})

Something like this should do it:

r([4, 3, 2, 1]).foreach(function(id) {
  return r.table('authors').get(id).replace(function(row) {
    return r.branch(row.eq(null), {id: id, videos: [1, 2, 3]}, row);
  });
});

lambda for replace method has only 1 argument. But you are trying too pass 2 args: author , index .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM