Эффективная и правильная стратегия обработки сортируемых элементов в базе данных - PullRequest
3 голосов
/ 06 января 2011

В веб-приложении у меня есть набор сущностей в базе данных с числовым полем, отвечающим за их порядок.На стороне клиента эти объекты отображаются в виде сортируемого списка, позволяющего пользователям изменять свой заказ.

На данный момент у меня есть два решения для управления обновлениями заказов, и ни одно из них меня не устраивает.

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

Второй вариант: когда пользователь изменяет порядок элементов,ID измененного элемента отправляется на сервер вместе с идентификаторами элементов, которые «окружают» измененный элемент в его новом месте в списке.На сервере новый заказ товара рассчитывается по (previous.order + next.order) / 2.Таким образом, если элемент с заказом 3 перемещается между элементами с заказами 5 и 6, его новый заказ становится 5,5
Это решение требует только одного обновления на изменение, но также имеет серьезную проблему: из-за используемого алгоритма каждое изменение увеличивает десятичную частьв порядковых номерах и рано или поздно это требует большей точности, чем может предоставить моя база данных (я использую MongoDB для этого случая, но я полагаю, это не так важно).

Мой вопрос заключается в том, существуют ли другие более эффективные и правильные способыили, может быть, мои нынешние подходы могут быть как-то улучшены?

Ответы [ 3 ]

5 голосов
/ 06 января 2011

Опишите порядок в базе данных с помощью порядкового номера, который начинается с 0 для первого элемента и увеличивается на 1 для каждого последующего элемента. Затем вам просто нужно отправить порядковые номера перемещенного элемента и порядковый номер его нового предыдущего соседа. Затем вы делаете (я использую $ для пометки переменных - вам нужно будет передать их в запросы из вашего кода):

-- if $moved > $previous, and it's moving backwards, move everything between the new previous neighbour and the item forward one
update items
set ordinal = ordinal + 1
where ordinal > $previous
and ordinal < $moved;

-- else $moved < $previous, and it's moving forwards, move everything between the item and the new previous neighbour backwards one
update items
set ordinal = ordinal - 1
where ordinal > $moved
and ordinal <= $previous;

-- then move the item
update items
set ordinal = $previous + 1
where ordinal = $moved;

Вы можете добавить уникальное ограничение к порядковому столбцу, чтобы обеспечить целостность, но вам нужно быть немного умнее в отношении того, как вы обновляли.

1 голос
/ 06 января 2011

Вы можете использовать связанный список в базе данных: Сбросьте столбец заказа и сохраните в этой строке либо предыдущий, либо следующий идентификатор.
Обновления тогда тривиальны (но дополнительная работа по отображению отсортированного списка).

1 голос
/ 06 января 2011

Я сделал нечто похожее на ваш второй подход.Вместо того, чтобы использовать двойные, я использовал целые числа и разделил элементы на 1000. Это помогло мне в моем приложении, так как количество элементов не должно превышать 4M.Позже, когда я определю, что приращение теперь уменьшено до 1 (или чего-то небольшого), я выдам команду сброса, которая снова установит интервалы в 1000.Я сделал это с помощью TSQL.

Надеюсь, это поможет!

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