mapmath
mapmath

Reputation: 1532

CouchDB Update Handler: doc update/insert using Nano

I am storing some locale based data in the following format in the CouchDB.

{
  "_id": "a62f81b5afad1857c2f6399db500c73b",
  "_rev": "3-923e5ed468e0f617f09057035b41051a",
  "type": "CAT",
  "origin_id": "1",
  "locale": "ar",
  "values_translation": {
    "id": "ar",
    "title": ""
  }
}

I use Nano as the client in Node JS app and I need to insert if not exists / update if exists docs using the Update Handler. for that I have created the following document in the couchDB;

  "_id": "_design/handler",
  "_rev": "36-d2d08a0a822a762ac07faa4042eca5a0",
  "updates": {
    "handler": "function(doc, req){ 
       if (doc.type === req.type && doc.origin_id === req.origin_id && doc.locale === req.locale)
       { return [doc, 'OK'];}
       else { return [null, 'KO']; }
    }"
  },
  "language": "javascript"
}

But When I run it using the following Nano Method,

translationsDB.atomic("handler", "handler", "_design/handler",
      { type, origin_id, locale, values_translation: value }).then((response) => {
        console.log(response);
      }).catch(err => {
        console.log(err);
      });

it always returns 'OK' even if I pass invalid data. For real data it returns OK but it does not update the document. Need to figure how to achieve this (update if the doc is existing or insert if it is a new doc) in right way.

Upvotes: 1

Views: 962

Answers (1)

lossleader
lossleader

Reputation: 13495

current code's behavior

Your custom field names like locale are undefined for both doc and req, since:

  1. doc.customfield, atomic("handler", "handler", "_design/handler" is calling the design on the design doc itself (3rd parameter to atomic is the document to update) and your design doc naturally lacks customfields you put on your example locale document.

  2. req.customfield, these are non-existent req fields, fields passed in by atomic are in JSON in req.body as shown in the atomic docs.

So your checks always pass for these fields, given undefined === undefined is true.

Then:

  1. you update the design doc without ever modifying doc:
{ return [doc, 'OK'];}

so couchdb saves the unchanged design doc (problem 1), causing only its _rev to keep going up:

{ "_id": "_design/handler", "_rev": "36-...

but it is the wrong document and no fields are being changed.

To fix these 3 problems

  1. Call it on the correct document:

    translationsDB.atomic("handler", "handler", "a62f81b5afad1857c2f6399db500c73b",

  2. Extract the customfields from req.body:

       var reqb = JSON.parse(req.body); 
       if (doc.type === reqb.type && doc.origin_id === reqb.origin_id && doc.locale === reqb.locale)
    
  3. Make some modification to the document being returned:

      { return [Object.assign({}, doc, reqb), 'OK'];}    
    

Upvotes: 2

Related Questions