Подходит ли модуль Ltree PostgreSQL для потоковых комментариев?

StackOverflow https://stackoverflow.com/questions/603894

Вопрос

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

Я думаю, что ltree (или что-то в этом роде) было бы полезно, если бы оно было связано с традиционным списком смежности ("comment_id" / "parent_comment_id").

Прежде чем приступить к использованию ltree, мне интересно узнать несколько вещей:

  1. Используете ли вы или уже использовали ltree?Это то, что можно было бы назвать "готовым к производству"?
  2. Если да, то для решения каких проблем вы использовали его?Хорошо ли это сработало?
  3. Считаете ли вы, что это хорошо подходит для многопоточной системы комментариев?
    1. Если вы использовали его, то что вы использовали для "текстовой" части пути?Вы настроили что-то вроде примера DMOZ, который они используют "Top.Astronomy.Cosmology", или основываете его на чем-то вроде первичного ключа "1.403.29.5"?
    2. Есть ли лучший способ сделать это?Я немного нервничаю, используя подход с вложенным списком - все, что я прочитал, говорит о том, что не все так просто с ОБНОВЛЕНИЯМИ или ВСТАВКАМИ (разве вам не нужно переупорядочивать все это?).Я также не специализируюсь в CS, и такая структура данных - это то, о чем я могу забыть в будущем.Кто-нибудь использует вложенные списки для комментариев или что-то в этом роде?

Если это может как-то помочь, вот схема, которую я рассматриваю:

CREATE TABLE comments (
    comment_id SERIAL PRIMARY KEY,
    parent_comment_id int REFERENCES comments(comment_id) ON UPDATE CASCADE ON DELETE CASCADE,
    thread_id int NOT NULL  REFERENCES threads(thread_id) ON UPDATE CASCADE ON DELETE CASCADE,
    path ltree NOT NULL,
    comment_body text NOT NULL,
    hide boolean not null default false
);

Столбец "путь", используемый ltree, будет выглядеть примерно так:

<thread_id>.<parent_comment_id_#1>.<parent_comment_id_#2>.<my_comment_id>

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

Это было полезно?

Решение

  1. Да и да;
  2. Иерархия разделов в базе знаний (одна из реализаций);
  3. ДА;

Определение одной из рассматриваемых таблиц:

                                                   Table "knowledgebase.section"
           Column           |           Type           |                                  Modifiers
----------------------------+--------------------------+-----------------------------------------------------------------------------
 section_sid                | integer                  | not null default nextval('knowledgebase.section_section_sid_seq'::regclass)
 section                    | character varying        | not null
 description                | character varying        |
 path                       | ltree                    | not null
 is_active                  | boolean                  | not null default true
 role_sid                   | integer                  | not null
 last_modified_by           | integer                  | not null
 creation_datetime          | timestamp with time zone | not null default now()
 last_modification_datetime | timestamp with time zone | not null default now()
 is_expanded                | boolean                  | not null default false
 section_idx                | tsvector                 |
Indexes:
    "section_sid_pkey" PRIMARY KEY, btree (section_sid)
    "section_section_key" UNIQUE, btree (section)
    "idxsection_idx" gist (section_idx)
    "path_gist_idx" gist (path)
Foreign-key constraints:
    "last_modified_by_fkey" FOREIGN KEY (last_modified_by) REFERENCES "user"."role"(role_sid) ON UPDATE CASCADE ON DELETE RESTRICT
    "role_sid_fkey" FOREIGN KEY (role_sid) REFERENCES "user"."role"(role_sid) ON  UPDATE CASCADE ON DELETE RESTRICT
Triggers:
    section_idx_update BEFORE INSERT OR UPDATE ON knowledgebase.section FOR EACH ROW EXECUTE PROCEDURE tsearch2('section_idx', 'section')

Столбец "путь" использует первичный ключ в качестве метки.

Пример текущего содержимого этой таблицы (относительно первичного ключа и столбца "путь"):

  section_sid | path
 -------------+-------
           53 | 34.53
           56 | 56
           55 | 29.55
           35 | 35
           54 | 34.54
           37 | 30.37
          ... | ...

Другие советы

Я рекомендую всем, кто реализует иерархические отношения в SQL, прочитать Деревья и иерархии Джо Селко в SQL для Smarties.

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

Одну стратегию (которую мне довелось использовать) также можно бесплатно найти в этой серии статей:

Версия 8.4 PostgreSQL привнесет функциональность общих табличных выражений в ядро с WITH и WITH... RECURSIVE выражения.Если вы модифицируете старый код, возможно, вам захочется дождаться выхода версии 8.4, так как тогда вам не придется беспокоиться о каких-либо несовместимостях между Ltree и новым синтаксисом ядра.Если вы работаете со старым кодом или не хотите ждать версии 8.4, вам, вероятно, захочется убедиться, что вы пишете код, который легко переводится в новый синтаксис, особенно если вы меняете старую схему или разрабатываете новую.

Смотрите также:

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top