Подходы для генерации автоматически увеличивающихся числовых идентификаторов в CouchDB - PullRequest
25 голосов
/ 22 февраля 2011

Так как CouchDB не поддерживает SQL, подобно AUTO_INCREMENT, каков будет ваш подход к созданию последовательных уникальных числовых идентификаторов для ваших документов?

Я использую числовые идентификаторы для:

  • Удобные идентификаторы (например, TASK-123, RQ-001 и т. Д.)
  • Интеграция с библиотеками / системами, для которых требуется числовой первичный ключ

Мне известны проблемы с репликацией.и т.д. Вот почему меня интересует, как люди пытаются преодолеть эту проблему.

Ответы [ 6 ]

35 голосов
/ 22 февраля 2011

Как говорит Доминик Барнс, целые числа с автоинкрементом не масштабируемы, не распределены и не облачны.Кажется, что каждое приложение в настоящее время нуждается в мобильной версии с поддержкой в ​​автономном режиме, которая не совместима напрямую с целыми числами с автоинкрементом.Мы все это знаем, но это так: целые числа с автоинкрементом необходимы для унаследованного кода и, возможно, других вещей.

В обоих сценариях вы несете ответственность за создание целого числа с автоинкрементом.Представление работает emit(the_numeric_id, null).(У вас также может быть пространство имен типа, например emit([doc.type, the_numeric_id], null). Запрос последней строки (например, с startkey=MAXINT&descending=true&limit=1, увеличьте возвращаемое значение, и это ваш следующий идентификатор. Попытка сохранения находится в циклекоторый может повторить попытку в случае столкновения.

Вы также можете играть трюки, если вам не нужна 100% -ная плотность списка идентификаторов. Например, вы можете добавить временные метки к строкам emit() иоцените скорость создания документа и увеличьте ее на величину, умноженную на ваши вычисления и время передачи. Вы также можете просто увеличить случайное целое число от 1 до N, поэтому большую часть времени первая вставка работает за счет неоднородного идентификаторачисла.

О том, где хранить целое число, я думаю, что есть стратегия id и стратегия try and check .

The * 1017Стратегия * id проще и быстрее за короткий промежуток времени . Идентификаторы документов являются целыми числами (возможно, с префиксом типа для добавления пространства имен). Так как Couch гарантирует уникальность _idполе, вы просто беспокоитесь об автоинкременте.Сделайте это в цикле: 409 Conflict запускает повтор, 201 Accepted означает, что вы закончили.

Я думаю, что основная боль в этом трюке заключается в том, что , если и когда вы получитеконфликты, у вас есть два совершенно не связанных документа, и один из них должен быть скопирован в новый документ.Если были отношения с другими документами, все они должны быть исправлены.(Вспоминается трюк CouchDB 0.11 emit(key, {_id: some_foreign_doc_id}).)

Стратегия try and check использует UUID по умолчанию в качестве doc._id, поэтому каждая вставка будет успешной.В идеале все или большинство ваших междокументарных отношений основаны на неизменяемом UUID _id, а не на целом числе.Это просто используется для пользователей и пользовательского интерфейса.Автоинкрементное целое число - это просто поле в документе {"int_id":20}.Мнение конечно делает emit(doc.int_id, null).(Вы можете искать документ по целочисленному идентификатору с параметром ?key=23?include_docs=true представления.

Конечно, после репликации могут возникнуть конфликты идентификаторов (не официальные конфликты CouchDB, а только документы, использующие тот жечисловой идентификатор). Представление, которое генерирует по идентификатору, также будет иметь фазу сокращения: достаточно просто _count. Затем вы должны патрулировать БД, запрашивая это представление с помощью ?group=true и ища любую строку (соответствующую целочисленному идентификатору).) с числом> 1. С другой стороны, исправление числового идентификатора документа является незначительным изменением, поскольку не требует создания нового документа.

Это мои идеи. Теперь, когда я их записалЯ чувствую, что вы должны выполнять пасти отношений независимо от того, где хранится идентификатор, поэтому, возможно, лучше использовать _id. Единственный другой недостаток, который я вижу, это то, что вы навсегда состоите в браке с принципиально нарушенной моделью именования - для некоторыхопределение понятия «навсегда»

3 голосов
/ 25 февраля 2011

Мне очень повезло, просто в качестве ключа использовалась дата в формате ISO:

http://wiki.apache.org/couchdb/IsoFormattedDateAsDocId

Это довольно просто сделать, удобочитаемо, и в основном оно включает в себя несколько вариантов запросов просто существующими. : -)

2 голосов
/ 22 февраля 2011

Есть ли какая-либо конкретная причина, по которой вы хотите использовать числовые идентификаторы над UUID, которые CouchDB может сгенерировать для вас? UUID идеально подходят для распределенной парадигмы, которую использует CouchDB, придерживайтесь того, что встроено.

Если вы обнаружите, что в вашей архитектуре имеется более 1 узла CouchDB, вы получите конфликтующие идентификаторы документа, если будете полагаться на что-то вроде «автоинкремента», когда придет время для репликации. Даже если вы сейчас используете только 1 узел, это, вероятно, не всегда будет иметь место, тем более что CouchDB так хорошо работает в распределенной и «автономной» архитектуре.

1 голос
/ 02 марта 2017

Не идеальное решение, но то, что сработало для меня.Создайте независимый сервис, который генерирует автоматически увеличивающиеся идентификаторы.Да, вы, вероятно, говорите «это нарушает автономную модель couchdb», но что, если вы получите пул N-идентификаторов, которые затем сможете использовать всякий раз, когда вам нужно получить новый автоматически увеличенный идентификатор.Затем каждый раз, когда вы онлайн, вы получаете еще несколько идентификаторов, и если у вас заканчиваются идентификаторы, вы говорите своим пользователям - пожалуйста, выходите в интернет.Если пул достаточно большой (скажем, месячный трафик), этого не должно произойти.Опять же, не идеально, но, возможно, может быть полезным для некоторых людей.

1 голос
/ 09 апреля 2015

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

function(doc, req) {
    if (!doc) {
        doc = {
            _id: req.id,
            type: 'idGenerator',
            count: 0
        };
    }
    doc.count++;
    return [doc, toJSON(doc.count)];
}

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

{
   "_id": "_design/application",
   "language": "javascript",
   "updates": {
       "generateId": "function (doc, req) {\n\t\t\tif (!doc) {\n\t\t\t\tdoc = {\n\t\t\t\t\t_id: req.id,\n\t\t\t\t\ttype: 'idGenerator',\n\t\t\t\t\tcount: 0\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tdoc.count++;\n\t\t\t\n\t\t\treturn [doc, toJSON(doc.count)];\n\t\t}"
   }
}

Тогда назовите это так:

curl -XPOST http://localhost:5984/mydb/_design/application/_update/generateId/entityId

Замените entityId тем, что вам нравится, чтобы создать несколько независимых последовательностей идентификаторов.

0 голосов
/ 15 ноября 2014

Вместо явного построения увеличивающегося целочисленного ключа вы можете использовать неявный индекс, который couchDB принимает для подкачки.

Параметр skip принимает целое число, которое эффективно обеспечивает индекс автоинкремента.Вы привыкли.

http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options

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

Если ваше единственное ограничение - «интеграция с библиотеками / системами, для которых требуется числовой первичный ключ», это устранит пробел безпотеря преимуществ ключевой структуры couchDB.

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