Обработчик обновлений CouchDB: обновление/вставка документа с использованием Nano

Я храню некоторые данные на основе локали в следующем формате в CouchDB.

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

Я использую Nano в качестве клиента в приложении Node JS, и мне нужно вставить, если он не существует/обновить если существуют документы с использованием обработчика обновлений. для этого я создал следующий документ в 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"
}

Но когда я запускаю его, используя следующий нано-метод,

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

он всегда возвращает 'OK', даже если я передаю неверные данные. Для реальных данных он возвращает OK, но не обновляет документ. Нужно понять, как этого добиться (обновить, если документ существует, или вставить, если это новый документ) правильным образом.


person mapmalith    schedule 13.08.2019    source источник
comment
Ваш метод обработчика никогда не возвращает новую структуру (новый документ), а только существующую, которая выглядит не совсем правильно. Вот ссылка на документ CouchDB по обработчикам обновлений, возможно, это поможет: docs.couchdb.org/en/stable/ddocs/   -  person chrisinmtown    schedule 13.08.2019


Ответы (1)


текущее поведение кода

Имена ваших настраиваемых полей, такие как locale, являются undefined как для doc, так и для req, поскольку:

  1. doc.customfield, atomic("handler", "handler", "_design/handler" вызывает дизайн в самом дизайн-документе (третий параметр atomic — это документ для обновления), и в вашем дизайн-документе, естественно, отсутствуют настраиваемые поля, которые вы добавили в свой пример документа локали.

  2. req.customfield, это несуществующие req поля, переданные atomic, находятся в формате JSON в req.body, как показано в документах atomic.

Таким образом, ваши проверки всегда проходят для этих полей, если undefined === undefined истинно.

Потом:

  1. вы обновляете проектный документ, никогда не изменяя документ:
{ return [doc, 'OK'];}

таким образом, Couchdb сохраняет неизмененный дизайн-документ (проблема 1), в результате чего продолжает расти только его _rev:

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

но это неправильный документ, и никакие поля не изменяются.

Чтобы решить эти 3 проблемы

  1. Назовите его в правильном документе:

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

  2. Извлеките настраиваемые поля из req.body:

       var reqb = JSON.parse(req.body); 
       if (doc.type === reqb.type && doc.origin_id === reqb.origin_id && doc.locale === reqb.locale)
    
  3. Внесите некоторые изменения в возвращаемый документ:

      { return [Object.assign({}, doc, reqb), 'OK'];}    
    
person lossleader    schedule 13.08.2019
comment
Спасибо за это хорошее объяснение, и в соответствии с вашим исправлением нам нужно передать id - a62f81b5afad1857c2f6399db500c73b, и в этом случае мне нужно будет получить DOC, запрашивающий БД, но одной из основных причин, по которой я использую обработчик обновлений, является обновление или вставка документа без запроса БД для повышения производительности. Есть ли способ добиться этого без передачи самого docID? - person mapmalith; 15.08.2019
comment
@mapmalith на самом деле нет, updatefun получает 1 doc на основе переданного идентификатора, если он существует или нет документа ... поскольку для обновления документа требуется его версия, поэтому он может обновить 1 документ, который он мог найти, с идентификатором, предоставленным клиентом, или создать любой новый документ с новым идентификатором. Способ избежать запроса состоит в том, чтобы не использовать случайные идентификаторы, а вместо этого определять уникальные идентификаторы, создавая ключ поиска из содержимого документа, чтобы вы знали, существует ли документ с идентификатором, его необходимо обновить, и если он не существует, его безопасно создавать. т.е. ваши идентификаторы будут установлены при создании как ${type}-${origin_id}-${locale}. - person lossleader; 15.08.2019