2009-03-02 8 views
8

Sto prendendo in considerazione l'utilizzo di Ltree module di PostgreSQL nella mia applicazione per aiutare con commenti a thread. L'ho messo da parte per un po 'di tempo per i commenti con thread. Immagino che sarebbe d'aiuto nei casi in cui è necessario aggiornare un nodo e i suoi figli, come quando si desidera nascondere un commento e le sue risposte.Il modulo Ltree di PostgreSQL è adatto per i commenti con thread?

Sto pensando a ltree (o qualcosa di simile) sarebbe utile se fosse abbinato ad una tradizionale lista di adiacenze ("comment_id"/"parent_comment_id").

Prima di prendere il tuffo in uso ltree, mi chiedo alcune cose:

  1. sei, o ha, ltree utilizzati? È quello che si potrebbe chiamare "produzione pronta"?
  2. Se sì, quali problemi l'hai usato per risolvere? Ha fatto un buon lavoro?
  3. Pensi che sia adatto per un sistema di commento con thread ?
    1. Se lo hai usato, cosa hai usato per la parte "testo" del percorso? Hai impostato qualcosa come l'esempio DMOZ che usano "Top.Astronomy.Cosmology" o basandolo su qualcosa come la chiave primaria "1.403.29.5"?
    2. C'è un modo migliore per farlo? Sono un po 'nervoso usando un approccio di elenco annidato - tutto quello che ho letto suggerisce che non è tutto molto caldo con gli AGGIORNAMENTI o INSERTI (non devi riordinare il tutto?). Inoltre, non sono un CS senior e quel tipo di struttura dei dati è qualcosa che potrei dimenticare in futuro. Qualcuno usa liste annidate per commenti o qualcosa del genere?

Se si tratta di alcun aiuto, qui è lo schema Sto pensando:

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 
); 

La colonna "percorso", usato da ltree, sarebbe simile:

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

C'è qualcosa di sbagliato nell'usare le chiavi primarie nel percorso? Dovrei includere la chiave primaria del nodo nel percorso? Se lo facessi, avrebbe senso inserire un indice univoco su di esso per fungere da vincolo?

+0

ltree è un'implementazione di "percorso materializzato". vedere http://www.dbazine.com/oracle/or-articles/tropashko4 per un confronto delle possibili soluzioni, compresi i metodi più portatili (ma meno efficienti) come i set annidati. – vladr

+0

sentiti libero di aggiungere questo come risposta. Sono aperto ad altre idee. Ho esaminato i set annidati, ma sembrano un rompicapo da implementare e piuttosto lenti sugli aggiornamenti/inserimenti (non devi spostare tutto in basso?). –

+0

oh, e stavo pensando di usare ltree in aggiunta alla lista di adiacenza. quindi "comment_id" e "parent_comment_id". quello che avevo in mente era di usare ltree per velocizzare le operazioni su un ramo –

risposta

6
  1. Sì e sì;
  2. Gerarchia di sezioni in una base di conoscenza (una delle implementazioni);
  3. Sì;

La definizione di una delle tabelle di cui trattasi:

            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') 

La colonna "percorso" utilizza la chiave primaria come etichetta.

Un campione il contenuto corrente della tabella che (per quanto riguarda la chiave primaria e la colonna "percorso"):

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

qual è il percorso come una stringa? stai usando testo o numeri? –

+0

In che modo i percorsi includono il proprio ID poiché viene calcolato quando viene inserito? Usi un trigger, un 'UPDATE' o qualcos'altro? – Un3qual

2

La versione 8.4 di PostgreSQL introdurrà le funzionalità di Common Table Expressions nel core con le espressioni WITH e WITH... RECURSIVE. Se stai modificando il vecchio codice, potresti voler attendere fino al rilascio dell'8,4, in quanto non dovrai preoccuparti di eventuali incompatibilità tra Ltree e la nuova sintassi principale. Se stai lavorando con codice vecchio, o non vuoi aspettare 8.4, probabilmente vorrai assicurarti di scrivere codice che sia facilmente traducibile con la nuova sintassi, specialmente se stai modificando uno schema vecchio o progettando un nuovo uno.

Consulta anche:

+0

che è molto, molto bello.Che con roba sembra che sarà utile per più di semplici commenti. Trovare i tag e i relativi tag correlati sembra un altro buon candidato perché sta facendo alcuni self-join. –

4

Raccomando a chiunque attuazione relazioni gerarchiche in SQL leggere Joe Celko's Trees and Hierarchies in SQL for Smarties.

Attraversare i collegamenti padre genitore con profondità arbitraria può essere molto inefficiente quando si utilizza solo un parent_id. Il libro descrive tecniche che rendono questo accesso veloce.

Una strategia (che mi capita di usare) può essere trovato anche gratuitamente in questa serie di articoli:

Problemi correlati