Изменить уведомление в CouchDB, когда поле установлено - PullRequest
7 голосов
/ 11 июня 2010

Я пытаюсь получать уведомления в опросе об изменении CouchDB, как только заданное поле установлено или изменено.Я уже взглянул на фильтры, которые можно использовать для фильтрации событий изменений (db/_changes?filter=myfilter).Однако я еще не нашел способ включить эту временную информацию, потому что в функции этого фильтра можно получить только текущую версию документа.

Есть ли возможность создать такой фильтр?

Если это не сработает, я мог бы экспортировать свое поле в отдельную базу данных и единственный опрос на предмет изменений в этой БД, но я бы предпочел сохранить свои данные по очевидным причинам.заранее!

1 Ответ

6 голосов
/ 11 июня 2010

Вы правы: фильтры и _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%. Однако я думаю, что это делает идею очень ясной. Также помните, что этот шаг не является обязательным, однако преимущество заключается в том, что вам никогда не придетсяизмени свой код клиента.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...