Ошибка pouchDB query () при обновлении документов - PullRequest
0 голосов
/ 29 мая 2018

Допустим, у меня есть эти три документа:

{ "_id": "11111", "type": "template", "name": "person" }
{ "_id": "22222", "type": "template", "name": "place" }
{ "_id": "33333", "type": "template", "name": "thing" }

У меня есть облачная база данных, а затем у меня есть устройство с синхронизацией pouchDB из этой базы данных.

Это шаги, которые яdo:

  1. Я синхронизирую обе базы данных вместе.Итак, теперь у меня есть самые последние версии этого документа на моем устройстве.
  2. Я запускаю приведенный ниже запрос и получаю все три шаблона, например, так:

Код

var template_obj = {};

return device_db.query('filters/templates')
.then((templates) => {
    for (let t of templates.rows) templates_obj[t.id] = true;
    return templates_obj;
});

фильтры / шаблоны

function (doc) {
  if(doc.type == "template")
    emit(doc._id);
}

возврат

{ "11111": true, "22222": true, "33333": true }

Обновляю шаблон: человек на облаке.И тогда я обновляю это снова.Таким образом, 2 ревизии прошли без синхронизации с моим устройством.

Я синхронизируюсь с моим устройством.

Теперь, когда я запускаю тот же запрос и получаю тольконазад документ, который я отредактировал.Что странно, потому что я не касался других документов.То же представление возвращает ожидаемые результаты в облаке, но не на устройстве.

return

{"11111": true}
Однако, если я сделаю следующий код, все шаблоны вернутся как обычно, и на устройстве появится тот же самый _rev из облака.Это означает, что синхронизация прошла успешно, а представление запуталось.

новый код

return device_db.allDocs({conflicts: true})
.then((data) => {
    for (let d of data.rows) {
        if(d.doc.type == "template") {
            templates_obj[d.doc._id] = true;
        }
    }
    return templates_obj;
 }).catch((err) => {
    console.log(JSON.stringify(err));
})

Я начинаю верить, что это ошибка, потому что если яуничтожьте мою базу данных и повторите эти шаги, я могу воспроизвести эту проблему.

Ответы [ 3 ]

0 голосов
/ 01 июня 2018

Поняв, что вы используете React Native, я думаю, что это на самом деле связано с PouchDB в React Native, и это действительно ошибка.Есть несколько сообщений об этом поведении:

0 голосов
/ 15 июля 2018

Это не ошибка в PDB, это, к сожалению, устаревшие компоненты в pouchdb-Reaction-native.Подтвержденный способ состоит в том, чтобы объединить pouchdb-Reaction-native самостоятельно следующим образом - тогда запросы будут работать так, как ожидается:

import PouchDB from 'pouchdb-core';
PouchDB
.plugin(require('pouchdb-adapter-asyncstorage').default)
.plugin(require('pouchdb-adapter-http'))
.plugin(require('pouchdb-mapreduce'))
.plugin(require('pouchdb-replication'))
.plugin(require('pouchdb-authentication'));
const localDB = new PouchDB(localDBname, {adapter: 'asyncstorage', auto_compaction: true});

Таким образом, можно быть уверенным, что все компоненты являются самыми последними.

0 голосов
/ 01 июня 2018

[править: похоже, что это ошибка в PouchDB с React Native.Я оставляю этот ответ, потому что он может быть полезен другими способами.]

Я подозреваю, что это некоторый побочный эффект с глобальной переменной template_obj, которую вы используете.Попробуйте console.log(templates.rows) напрямую, вместо того, чтобы хранить его в переменной в верхней области, или используйте Array.reduce(), чтобы избежать побочных эффектов.Тогда вы всегда получите правильные результаты просмотра.

Это пошаговый код:

return device_db.query('filters/templates')
  .then(templates => templates.rows)            // Take only the rows into account.
  .then(rows => rows.map(row => row.id)         // Extract the id. If you wanted the name instead this would be possible with a slightly different view.
                                                // I think it would suffice to log the result right now, 
                                                // but if you really want to have a single object with boolean values, 
                                                // you can do the following:
  .then(ids => ids.reduce((asObject, id) => {   // Use Array.reduce() here to avoid any potential side effects.
    asObject[id] = true;
    return asObject;
  }, {})
  .then(asObject => { console.log(asObject); }; // Debug the result.

Или более кратко с ES2015 +:

return device_db.query('filters/templates')
  .then(({rows}) => rows.reduce((acc, {id}) => ({...acc, [id]: true }), {}))
  .then(result => console.log(result))

Поспособ: вы также можете использовать другие стратегии, чтобы «фильтровать» ваши документы, так как нет необходимости выдавать _id.Вместо этого вы можете использовать ключ и / или значение для «вторичных индексов»:

{
  "_id": "_design/docs",
  "views": {
    "byType": "function(doc) { emit(doc.type); }",
    "templatesByName": "function(doc) { if (doc.type === 'template') emit(doc.name); }",
    "byTypeAndName": "function(doc) { emit([doc.type, doc.name], doc.name); }
  }
}
  • вы можете использовать docs / byType в качестве универсального представления также для других типов документов.Просто позвоните по номеру db.query('docs/byType', { key: 'template' })
  • Если вы хотите, чтобы шаблоны сортировались по имени, используйте db.query('docs/templatesByName') или db.query('docs/byTypeAndName', { startkey: ['template'], endkey: ['template', {}]}).

Предупреждение: это все не проверено итолько из памяти, поэтому некоторые скобки могут отсутствовать в коде, или некоторые ошибки могут скрываться там.

...