Как перемещать элемент в отсортированном списке и держать CouchDb в записи "атомарным",

У меня есть элементы списка в документах couchdb. Скажем, это 3 элемента в трех документах:

{ "id" : "783587346", "type" : "aList", "content" : "joey", "sort" : 100.0 }
{ "id" : "358734ff6", "type" : "aList", "content" : "jill", "sort" : 110.0 }
{ "id" : "abf587346", "type" : "aList", "content" : "jack", "sort" : 120.0 }

Вид получает все "aList" документы и отображает их отсортированными по "сортировке".

Теперь я хочу переместить элементы, когда я хочу переместить "домкрат" в середину, я мог бы сделать это атомом в одной записи и изменить его ключ сортировки на 105.0. Теперь представление возвращает документы в новом порядке сортировки.

После большой сортировки я мог бы закончиться сортировочными ключами, такими как 50.99999 и 50.99998 через несколько лет, а в экстремальных ситуациях закончились цифры?

Что вы можете посоветовать, есть ли лучший способ сделать это? Я бы предпочел сохранить элементы в отдельных документах. Различные пользователи могут редактировать разные элементы списка параллельно.

И пользователи могут также изменить порядок документов одновременно (что также может стать сложным, когда 2 пользователя хотят переместить два разных документа (например, joey и jill) до конца, и пусть скажет "sort" = 130.0 на том же время).

Может быть, есть намного лучший способ?

Я что-то пропустил на транзакциях CouchDb?

Ответы

Ответ 1

Вы используете общий шаблон реального числа для пользовательского управления сортировкой. Это прекрасный способ, рекомендованный Дэмиеном Кацем. Чтобы перемещаться между соседними документами A и B, вы устанавливаете в поле sort среднее значение A.sort и B.sort.

Этот вопрос состоит из нескольких частей.

Как насчет точности с плавающей запятой?

Javascript Number - это номера с плавающей запятой с двойной точностью IEEE-754. Oни имеют ограниченную точность.

У парней много точности. Если это деятельность, инициированная человеком, то она будет очень долго, пока перетаскивание не достигнет предела. Но у вас есть два варианта:

1. Повторно нормализовать значения сортировки в фоновом режиме

Помните, что вы переписываете номера строк в BASIC? То же самое.

У вас есть задание cron или какая-то другая задача (NodeJS становится популярным) чтобы проверить неприемлемо близкие значения сортировки и освободить их. Эта могут использовать сложные эвристики, такие как:

  • Подождите, пока сайт будет находиться под низкой активностью, чтобы исправить sort s
  • Подождите, пока конкретный пользователь не будет активен в течение X-времени, прежде чем устанавливать его sort s
  • Делайте только модификации, которые выделяют значения sort, но которые никогда не меняются результат обзора. Другими словами, если у вас есть 0.001, 0.002 и 0.003, сначала переместите 0.003, например. 0.100, затем измените 0.002 на 0.005. Что может иметь небольшой полезный эффект в пользовательском интерфейсе, но помните, что репликация может не скопируйте их в том же порядке, чтобы преимущество было незначительным, возможно, не стоит сложность.

2. Используйте десятичный тип данных с неограниченной точностью

Вместо sort хранения Javascript Number он может хранить строку из но не включая "0.0" через "1.0" (скажем, до 100 цифр). Затем сортировка строки также числовой вид. (У вас есть "привязки" в 0.0 и 1.0, которые недопустимы для документов. Чтобы вставить документ в первую позицию, установите sort в среднее значение 0.0 и текущий первый документ. Для последней позиции sort среднее значение последнего документа и 1.0.)

Затем ваш клиент (кто бы ни рассчитывал значение sort) произвольные типы реальных чисел. Java, Ruby, Python, почти все языки имеют их. Этот пост даже вдохновил меня на быстрый проект, BigDecimal для Javascript, который является BigDecimal код из Google Web Toolkit (который сам пришел из Apache Harmony). Но есть также являются другими реализациями.

Мне лично нравится BigDecimal. В вашем случае, однако, вам придется изменить свой код для использования строки для sort. Однако преимущество заключается в том, что вам никогда не придется нормализовать sort, чтобы обойти точность.

Как насчет столкновений от одновременной активности?

CouchDB Relaxed. Что произойдет, что ожидают пользователи. CouchDB документы имитируют реальный мир. Как говорит Крис Андерсон, "нет транзакций в реальной жизни ".

Для трех элементов в пользовательском интерфейсе:

  • Itema
  • ItemB
  • ItemC

Что делать, если я перемещаю A после C и перемещаю B после C? Ясно, что список будет либо C B A или C A B. Что это должно быть? Это зависит от вашего приложения?

Либо, это не имеет значения: Отлично! CouchDB будет произвольно заказывать A и B, и вы будет хорошо. Пользователи будут выходить (или посмотреть, хорош ли ваш пользовательский интерфейс), что кто-то еще перемещал другой элемент.

Или, B должен прийти раньше A, потому что [по какой-то причине]: ну, ваше значение sort неверно. Он должен включать все соответствующие данные для определения подтипов. Например, вы можете emit([120.000, doc.userLastName], doc). Когда пользователи перемещают документы в одно и то же место, сортировка становится в алфавитном порядке.

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

Ответ 2

Как насчет добавления 10 к чему-либо >= 110, а затем обновлению записи 130 до 110? Это позволяет сохранять чистые интервалы. Не идеально подходит для записей, которые часто обновляются несколькими пользователями, а также для огромных таблиц, но я успешно использую эту технику на небольшой и довольно статической таблице.

Ответ 3

Является ли нынешняя система действительно атомной? В конце концов, чтобы переместить дом между Джои и Джилл, нам нужно знать ценности joey и jill, которые требуют, чтобы они были запрошены в первую очередь. Совершенно очевидно, что промежуток времени 105,0 вычисляется, значения joey и jill также изменились. На самом деле, я считаю, что единственный способ, которым это могло бы работать на землях SQL, - заблокировать соответствующие строки, в то время как происходит переупорядочение, что приведет к сериализации запросов повторного заказа.

Возможно, более подробная информация о проблеме будет более полезной.