Вступление
Разработчики часто спрашивают меня, как «оформить» документы с помощью Couchbase 2.0. Короткий ответ: клиенты и сервер не предоставляют такую возможность, но ее довольно легко реализовать.
В этой статье я буду использовать базовый подход, и вы сможете расширить его в зависимости от ваших бизнес-требований.
дизайн
Первое, что нужно сделать, это выбрать, как «хранить / упорядочить» версии вашего документа, и для этого у вас есть разные дизайны:
- скопировать версии документа в новые документы
- скопировать версии документа в список вложенных документов
- хранить список атрибутов, которые были изменены во встроенный элемент (или новые документы)
- хранить «дельта»
- …
Вам нужно будет выбрать дизайн в соответствии с требованиями вашего приложения (бизнес-логика, размер набора данных и т. Д.). В этой статье давайте воспользуемся одним из самых простых подходов: создайте новый документ для каждой версии со следующими правилами для ключей:
- Текущая версия представляет собой простой ключ / документ, без изменений ключа.
- Версия является копией документа, а номер версии добавляется к ключу.
Это выглядит так:
Текущая версия | мой ключ |
Версия 1 | MyKey :: v1 |
Версия 2 | MyKey :: v2 |
… | … |
При таком подходе существующие приложения всегда будут использовать текущую версию документа, поскольку ключ не изменяется. Но этот подход создает новые документы, которые будут проиндексированы существующими представлениями.
Например, в приложении «Образец пива» для просмотра пива по имени используется следующий вид:
1
2
3
4
5
|
function (doc, meta) { if (doc.type && doc.type == "beer" ) { emit(doc.name); } } |
Поддерживать управление версиями довольно просто, не затрагивая существующий код, кроме самого представления. Новое представление должно излучать ключи, значение только для текущей версии документа. Это новый код вида:
1
2
3
4
5
|
function (doc, meta) { if (doc.type && doc.type == "beer" && (meta.id).indexOf( "::v" ) == - 1 ) { emit(doc.name); } } |
С этим изменением существующие приложения, использующие это представление, продолжат работать с тем же поведением.
Реализация управления версиями
Исходя из этой схемы, когда приложению требуется версия документа, должна произойти следующая логика:
- Получить текущую версию документа
- Увеличьте номер версии (например, используя другой ключ, который поддерживает номер версии для каждого документа)
- Создайте версию с новым ключом «mykey :: v1»
- Сохранить документ текущей версии
Давайте посмотрим на код в Java
01
02
03
04
05
06
07
08
09
10
11
12
|
Object obj = client.get(key); if (obj != null ) { // get the next version, create or use the key: mykey_version long version = client.incr(key + "_version" , 1 , 1 ); String keyForVersion = key + "::v" + version; // mykey::v1 try { client.set(keyForVersion, obj).get(); } catch (Exception e) { logger.severe( "Cannot save version " + version + " for key " + key + " - Error:" + e.getMessage() ); } } client.set(key, value); |
Довольно просто, не так ли?
Приложение может получить доступ к документу с помощью ключа, но также получить одну версию или список всех версий, это одна из причин, по которой интересно создавать ключ (
mykey_version), и используйте его также для удаления документов и связанных версий.
Исходя из предыдущего комментария, операция удаления выглядит следующим образом:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
Object obj = client.get(key); // need to delete all the version first Object vObject = this .get(key + "_version" ); if (vObject != null ) { long biggerVersion = Long.parseLong((String) vObject); try { // delete all the versions for ( int i = 1 ; i <= biggerVersion; i++) { String versionKey = key + "::v" + i; client.delete(versionKey).get(); } // delete the counter client.delete(key + "_version" ).get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } client.delete(key); |
Использовать управление версиями
В качестве примера, я создал небольшую библиотеку, доступную на GitHub https://github.com/tgrall/couchbase-how-to-versioning , эта библиотека расширяет клиент Couchbase и переопределяет некоторые операции: установить, заменить и удалить. (основной: нет TLL, нет долговечности) Как я уже говорил, это всего лишь пример.
Сборка и установка
1
2
3
|
git clone https: //github.com/tgrall/couchbase-how-to-versioning.git cd how-to-versioning mvn clean install |
Затем добавьте эту библиотеку в свой проект в дополнение к Couchbase Java Client, например, в свой pom.xml
01
02
03
04
05
06
07
08
09
10
11
|
... com.couchbase.howtos couchbase-how-to-versioning 1.0-SNAPSHOT couchbase couchbase-client 1.1.8 ... |
Код вашей заявки
Создайте документ и установите его версию:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
List uris = new LinkedList(); CouchbaseClientWithVersioning client = null try { client = new CouchbaseClientWithVersioning(uris, "default" , "" ); String key = "key-001" ; client.set(key, "This is the original version" ); System.out.printf( "Original '%s' .\n" , client.get(key)); client.set(key, "This is a new version" , true ); // create a new version System.out.printf( "Current Version '%s' .\n" , client.get(key)); System.out.printf( "Version 1 '%s' .\n" , client.get(key, 1 )); client.set(key, "This is another version" , true ); // create a new version System.out.printf( "All versions %s .\n" , client.getAllVersions(key)); client.deleteVersion(key, 1 ); // create a new version System.out.printf( "All versions %s (after delete 1 version).\n" , client.getAllVersions(key)); client.delete(key); // create a new version System.out.printf( "All versions %s (after delete the main key).\n" , client.getAllVersions(key)); } catch (Exception e) { e.printStackTrace(); } if (client != null ) { client.shutdown(); } |
Быстрое объяснение:
- Строка 5: вместо использования CouchbaseClient приложение использует расширенный класс CouchbaseClientWithVersioning.
- Строка 7: создать новую запись
- Строка 9: создайте новую версию, логическое значение «true» принудительно версирует документ
- Приложение использует другие методы, такие как получение определенной версии (строка 11), получение всех версий (строка 13), удаление определенной версии (строка 14) и, наконец, удаление ключа и всех версий (строка 16).
Таким образом, используя этот подход, разработчик явно контролирует, когда создавать версию, поскольку он должен добавить логический параметр в операции set. В этой небольшой библиотеке примеров также возможно автоматическое управление версиями, в этом случае все вызовы set и replace создадут версию для достижения того, что разработчику просто нужно вызвать метод setAutoVersioning (true). Что-то типа:
1
2
|
client = new CouchbaseClientWithVersioning(uris, "default" , "" ); client.setAutomaticVersionning( true ); |
При таком подходе вы можете обеспечить управление версиями вашего приложения с минимальным изменением кода. Вы можете протестировать его в приложении Beer Sample, просто не забудьте изменить представления, как указано выше, только для возврата
текущая версия документов.
Вывод
Как вы можете видеть, создание версий в Couchbase не так сложно, но это то, что должно быть сделано вашим приложением на основе его требований и ограничений. У вас есть много разных решений, и ни один из этих вариантов не подходит для всех вариантов использования.
В этом конкретном примере кода я работаю с простым проектом, в котором я создаю копию документов для каждой версии. Также при таком подходе интересно упомянуть, что вы можете создавать «все», не только документ JSON, но и любые значения. Как я уже говорил, это один из возможных подходов, и, как и любой дизайн, он оказывает некоторое влияние на приложение или базу данных, в данном случае большую часть базы данных:
- Увеличьте количество ключей и документов
- Удвойте или увеличьте число операций, например, при обновлении документа, приложение должно получить текущее значение, создать версию, сохранить текущую версию.
- Управление согласованностью при добавлении новой версии и увеличении номера версии (необходимо учитывать ошибки при создании новой версии, удалении версий и счетчика….)
Многие функции могут быть добавлены к этому легко, например:
- Ограничение до определенного количества версий,
- Включить управление версиями только операции replace ()
- Добавить определенный атрибут о версиях в документ JSON (например, дату версии)
- ….
Если вы используете управление версиями в своем приложении Couchbase, не стесняйтесь комментировать или написать небольшую статью, которая описывает, как вы это делаете.