Вы правы: фильтры и _changes
каналы могут видеть только снимки документа.Вам нужна функция, которая может видеть старый документ и новый документ и работать правильно.Но это недоступно в _filters
и _changes
.
Очевидно, ваш клиентский код знает, обновляет ли это поле.Вы можете обновить свой клиентский код, однако есть лучшее решение.
Функции обновления могут получить доступ к обоим документам. Я предлагаю вам создать функцию _update, которая замечает изменение поля и отмечает это в документе,Далее у вас есть простая проверка фильтра для этого флага.Самое приятное то, что вы можете использовать функцию перезаписи, чтобы сделать HTTP API точно таким же, как и раньше.
1.Создайте функцию обновления для пометки интересных обновлений
Ваш _design/myapp
будет {"updates", "smart_updater": "(see below)"}
.Функции обновления очень гибкие (см. Мои недавние обработчики обновлений пошаговое руководство).Однако мы только хотим имитировать обычный HTTP / JSON API.
Ваше поле updates.smart_updater
будет выглядеть так:
function (doc, req) {
var INTERESTING = 'dollars'; // Set me to the interesting field.
var newDoc = JSON.parse(req.body);
if(newDoc.hasOwnProperty(INTERESTING)) {
// dollars was set (which includes 0, false, null, undefined
// values. You might test for newDoc[INTERESTING] if those
// values should not trigger this code.
if((doc === null) || (doc[INTERESTING] !== newDoc[INTERESTING])) {
// The field changed or created!
newDoc.i_was_changed = true;
}
}
if(!newDoc._id) {
// A UUID generator would be better here.
newDoc._id = req.id || Math.random().toString();
}
// Return the same JSON the vanilla Couch API does.
return [newDoc, {json: {'id': newDoc._id}}];
}
Теперь вы можете PUT или POST к /db/_design/myapp/_update/[doc_id]
, и этобудет выглядеть как обычный API, за исключением , если вы обновите поле долларов, он добавит дополнительный флаг , i_was_changed
.Вот как вы найдете это изменение позже.
2.Фильтр для документов с измененным полем
Это очень просто:
function(doc, req) {
return doc.i_was_changed;
}
Теперь вы можете запросить фид _changes
с параметром ?filter=
.(Репликация также поддерживает этот фильтр, поэтому вы можете извлекать в свою локальную систему все документы, которые недавно изменили / создали поле.
Это основная идея. Остальные шаги сделают вашу жизнь проще, если у вас уже естьмного клиентского кода и не хотят изменять URL-адреса.
3. Используйте переписывание, чтобы сохранить HTTP API таким же
Это доступно в CouchDB 0.11, и лучшим ресурсом является блог Яна.post, хороших URL-адресов в CouchDB .
Вкратце, вам нужен виртуальный хост, который отправляет весь трафик вашему переписывающему устройству (который сам по себе является гибким "вышибалым" для всей функциональности doc на основе URL-адреса)).
curl -X PUT http://example.com:5984/_config/vhosts/example.com \
-d '"/db/_design/myapp/_rewrite"'
Тогда вам нужно поле rewrites
в вашем дизайн-документе, что-то вроде (не проверено)
[
{
"comment": "Updates should go through the update function",
"method": "PUT",
"from": "db/*",
"to" : "db/_design/myapp/_update/*"
},
{
"comment": "Creates should go through the update function",
"method": "POST",
"from": "db/*",
"to" : "db/_design/myapp/_update/*"
},
{
"comment": "Everything else is just like normal",
"from": "*",
"to" : "../../../*"
}
]
(Еще раз, я получил этот код из примеров исуществующий код, который я выложил, но он не отлажен на 100%. Однако я думаю, что это делает идею очень ясной. Также помните, что этот шаг не является обязательным, однако преимущество заключается в том, что вам никогда не придетсяизмени свой код клиента.)