2016-07-14 3 views
1

У меня есть nodejs приложение, в котором я подключиться к моей CouchDB, используя nano со следующим сценарием:CouchDB дизайн обновление док

const { connectionString } = require('../config'); 

const nano = require('nano')(connectionString); 

// creates database or fails silent if exists 
nano.db.create('foo'); 

module.exports = { 
    foo: nano.db.use('foo') 
} 

Этот скрипт выполняется на каждом запуске сервера, поэтому он пытается создать базу данных «Foo 'каждый раз, когда сервер (re) запускается и просто терпит неудачу, если база данных уже существует.

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

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

... 
nano.db.create('foo'); 

const foo = nano.db.use('foo'); 

const design = { 
    _id: "_design/foo", 
    views: { 
    by_name: { 
     map: function(doc) { 
     emit(doc.name, null); 
     } 
    } 
    } 
} 

foo.insert(design, (err) => { 
    if(err) 
    console.log('design insert failed'); 
}) 

module.exports = { 
    foo 
} 

Очевидно, что это будет только вставить проект doc, если он не существует. Но что, если я обновляю свой проект doc и хочу его обновить?

Я пробовал:

foo.get("_design/foo", (err, doc) => { 
    if(err) 
    return foo.insert(design); 

    design._rev = doc._rev 
    foo.insert(design); 
}) 

Сейчас проблема заключается в том, что дизайн документ обновляется каждый раз, когда перезапуск сервера (например он получает новую _rev при каждом перезапуске).

Теперь ... мой вопрос (ы) :)

1: Является ли это плохой подход для самонастройки мой CouchDB с базами данных и конструкций? Должен ли я рассматривать некоторые шаги миграции как часть моего процесса развертывания?

2: Является ли проблема, что мой проект doc получает много _revs, в основном для каждого развертывания и перезапуска сервера? Даже если сам документ не изменился? И если да, существует ли способ обновить документ, если он изменился? (Я думал о том, чтобы вручную установить _rev в какое-то значение в моем приложении, но очень не уверен, что это будет хорошая идея).

ответ

2
  1. Ваш подход кажется вполне разумным. Если проверки происходят только при перезагрузках, это даже не проблема производительности.
  2. Слишком много _rev s может стать проблемой. История _revs хранится как _revs_info и хранится с самим документом (see the CouchDB docs for details). В зависимости от вашей настройки может быть неправильным решением создать ненужные изменения.

У нас была аналогичная проблема с некоторыми серверными сценариями, которые требовали определенных видов. Наше решение состояло в том, чтобы вычислить хэш поверх старого и нового проектного документа и сравнить их. Вы можете использовать любую функцию хэширования для этого задания, например sha1 или md5. Не забудьте удалить _rev из старого документа перед его хэшированием, иначе вы будете получать разные значения хэша каждый раз.

+0

Спасибо, Бернхард. Ваше объяснение было действительно полезным. Я принял ваш совет, просто сравнив документы по дизайну, но столкнулся с некоторыми проблемами, сравнивая их с md5 ... Я разместил собственное решение на основе ваших предложений ниже. Не могли бы вы дать свой отзыв? –

1

Я попробовал сравнение md5, как предложил @ Бернхард Гшваннер. Но я столкнулся с некоторыми трудностями, потому что в моем случае я хотел бы написать функции map/reduce в проектных документах в чистом javascript в своем коде.

const design = { 
    _id: "_design/foo", 
    views: { 
    by_name: { 
     map: function(doc) { 
     emit(doc.name, null); 
     } 
    } 
    } 
} 

при получении дизайн документ от CouchDB возвращает карту/свертка функции преобразуются в строки:

... 
    "by_name": { 
    "map": "function (doc) {\n  emit(doc.name, null);\n  }" 
    }, 
    ... 

Очевидно md5 сравнения действительно не работает здесь.

Я закончил с очень простым решением, просто поставив номер версии на дизайн доке:

const design = { 
    _id: "_design/foo", 
    version: 1, 
    views: { 
    by_name: { 
     map: function(doc) { 
     emit(doc.name, null); 
     } 
    } 
    } 
} 

Когда я обновить дизайн док, я просто увеличить номер версии и сравнить его с номером версии в базе данных:

const fooDesign = {...} 
foo.get('_design/foo', (err, design) => { 
    if(err) 
    return foo.insert(fooDesign); 

    console.log('comparing foo design version', design.version, fooDesign.version); 
    if(design.version !== fooDisign.version) { 
    fooDesign._rev = design._rev; 
    foo.insert(fooDesign, (err) => { 
     if(err) 
     return console.log('error updating foo design', err); 
     console.log('foo design updated to version', fooDesign.version) 
    }); 
    } 
}); 
+0

Это тоже замечательно и намного проще. Однако, если вы хотите использовать хеширование md5, вы можете преобразовать функции javascript в строки, преобразовывая их в строки, итерируя через свойства объекта и вызывая 'prop.toString()'. Но это больше работает, поэтому поле версии является гораздо более простым и понятным решением. –

0

Пересматривая свой вопрос еще раз: в недавнем проекте я использовал большой couchdb-push модуль Йоханнес Шмидт. Вы получаете условные обновления бесплатно, наряду с manyotherbenefits унаследовано от его зависимости couchdb-compile.

Эта библиотека оказалась скрытой жемчужиной для меня. Настоятельно рекомендуется!

Смежные вопросы