Как переместить элемент в отсортированном списке и сохранить запись CouchDb «атомарно» - PullRequest
15 голосов
/ 31 мая 2010

У меня есть элементы списка в документах couchdb. Допустим, это 3 элемента в 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" и отображает их, отсортированные по "sort".

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

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

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

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

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

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

Ответы [ 3 ]

20 голосов
/ 10 июня 2010

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

.

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

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

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

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

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

Помните переписывать номера строк в бейсике? То же самое.

Иметь работу 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 расслаблен. Что произойдет, то, что пользователи ожидают. 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 переместился , то это тоже приложение код, который должен быть реализован независимо от хранилища данных. Другими словами, это нетранзакционная вещь, это программная логика. Для перетаскивания элементов пользовательского интерфейса, у меня такое чувство, что оно того не стоит, и решение "это не имеет значения" лучше.

1 голос
/ 10 июня 2010

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

0 голосов
/ 05 июня 2010

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

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

...