LINUX.ORG.RU

Сортировка объектов

 , , , ,


0

2

Всем привет. Есть задача: обеспечить возможность сортировки объектов пользователями. (т.е. на странице есть некий список и пользователь drag-n-drop`ом его сортирует как ему нужно)
Сложность возникает в тот момент, когда нужно эту сортировку сохранить в базе данных.
У меня есть 2 варианта:
1) У каждого списка создать поле, в котором упорядоченно хранить список id элементов списка.
2) У каждого элемента создать поле weight и по этому полю сортировать выборку

А теперь представьте:
* элемент 1
* элемент 2
* элемент 3
...
* элемент 10000
Количество элементов никак не ограничено.

При использовании 1 варианта: представьте поле, в котором будет храниться список из тысяч элементов. Теряется весь смысл базы данных. Да и сортировать всю выборку по такому массиву будет не удобно.
При использование 2 варианта: если сдвигается хоть один элемент, значение weight придется перезаписывать для всех последующих. Даже если указывать weight с некоторым шагом (например 10), рано или поздно придется пересчитывать для всего списка.

Собственно, вопрос: как лучше организовать упорядоченное хранение объектов?



Последнее исправление: Dmit3Y (всего исправлений: 1)

Даже если указывать weight с некоторым шагом (например 10), рано или поздно придется пересчитывать для всего списка.

Можно хранить это в виде чисел с плавающей точкой. Врят ли тогда придется пересчитывать для всего списка.

А вообще такое можно хранить в базе данных в виде деревьев.

Siado ★★★★★
()
Ответ на: комментарий от Siado

Хм. С плавающей точкой очень хороший вариант. Как-то не задумался.
Спасибо.

Dmit3Y
() автор топика
Ответ на: комментарий от Kalashnikov

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

Dmit3Y
() автор топика
Ответ на: комментарий от Siado

Можно хранить это в виде чисел с плавающей точкой

Проблем с точностью не возникнет?

Я думаю, что деревья более практичный вариант. Тем более, что есть nested sets.

k0valenk0_igor ★★★
()
Последнее исправление: k0valenk0_igor (всего исправлений: 1)
Ответ на: комментарий от k0valenk0_igor

Структура же не такая сложная. Но возможно я не до конца понял суть nested sets.
А вот с погрешностью float беда. Она сильно большая.

Dmit3Y
() автор топика

Решение где-то рядом.

При использовании 2 варианта: если сдвигается хоть один элемент, значение weight придется перезаписывать для всех последующих. Даже если указывать weight с некоторым шагом (например 10), рано или поздно придется пересчитывать для всего списка.


Можно же сразу все последующие записи обновить запросом и увеличить weight.

UPDATE item.order = item.order + 1 FROM item WHERE order > 3;

Dmit3Y
() автор топика
Ответ на: комментарий от k0valenk0_igor

Благодарю. Уже нагуглил это и прочитал. Стало понятнее. Однако, с использованием SQL, это будет слишком ресурсоемко. При выборке для каждого элемента будет выполнятся 1 запрос. Даже если получить все сразу с определенной ветки, перебором собирать в единый массив для вывода в шаблоне будет долго.

Dmit3Y
() автор топика
Ответ на: комментарий от Dmit3Y

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

Или даже вот это

k0valenk0_igor ★★★
()
Последнее исправление: k0valenk0_igor (всего исправлений: 1)

Питонщики такие питонщики))
http://yadi.sk/d/XZoB29Vh3uL2S (.png)
Никак же нельзя закрепить решение типичных задач в виде библиотек да?))
Как например.. https://github.com/swanandp/acts_as_list

пс
драгндропом 1000 элементов ты не отсортируешь -_-

special-k ★★★★
()
Последнее исправление: special-k (всего исправлений: 1)
Ответ на: комментарий от Dmit3Y

Как вариант. Но мне кажется, что будет слишком много запросов к базе.

Отчего же много запросов? Допустим есть БД:

CREATE TABLE `User` (
    `id` meduimint(9) NOT NULL AUTO_INCREMENT,
    `name` varchar(60) NOT NULL,
    PRIMARY KEY (`id`)
);

CREATE TABLE `Record` (
    `id` mediumint(9) NOT NULL AUTO_INCREMENT,
    `text` varchar(60) DEFAULT '',
    `user` mediumint(9) NOT NULL,
    `parent` mediumint(9) DEFAULT NULL,
    PRIMARY KEY (`id`),
    FOREIGN KEY (`user`) REFERENCES `User` (`id`) ON DELETE  CASCADE ON UPDATE CASCADE,
    FOREIGN KEY (`parent`) REFERENCES `Record` (`id`)
);

Всё что вам нужно: индекс по полю `Record`(`user`) и запрос вида:

SELECT * FROM `Record` WHERE `user` = :user;

Нужно же потом как-то собрать этот список в массив.

А это уже дело техники. Элементарная сортировка по полю `parent`.

KennyMinigun ★★★★★
()
Последнее исправление: KennyMinigun (всего исправлений: 2)

если сдвигается хоть один элемент, значение weight придется перезаписывать для всех последующих


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

pi11 ★★★★★
()
Последнее исправление: pi11 (всего исправлений: 1)
Ответ на: комментарий от KennyMinigun

Как вариант.
Теперь предстоит выбрать из всех предложенных вариантов.

Dmit3Y
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.