2009-06-29 16 views
2

Ich habe Property-Management-Anwendung von Tabellen aus:über mehrere Tabellen Suche (best practices)

tenants 
landlords 
units 
properties 
vendors-contacts 

Grundsätzlich möchte ich ein Suchfeld, sie alle eher suchen als die Kategorie auszuwählen, die ich suche. Wäre dies eine akzeptable Lösung (technisch klug?)

Wird die Suche über 5 Tabellen auf lange Sicht in Ordnung sein und den Server nicht blockieren? Was ist der beste Weg, dies zu erreichen?

Mit PostgreSQL

+0

Tabellen serialisiert und mit [Xapian] (http://xapian.org/) und [Python-xapian] (http:// Xapian.org/docs/bindings/python /) Bindung (Wrapper). – zinovii

Antwort

3

Ich würde vorschlagen, ein spezialisiertes Volltext-Indexierungswerkzeug wie Lucene dafür zu verwenden. Es wird wahrscheinlich einfacher sein, aufzustehen, und das Ergebnis ist schneller und mehr Feature auch. Postgres-Volltextindizes sind nützlich, wenn Sie darüber hinaus eine strukturierte Suchfunktion benötigen oder die Transaktionalität Ihres Suchindex wichtig ist.

Wenn Sie dies nicht möchten, in der Datenbank implementieren, könnte so etwas wie das folgende Schema arbeiten, verwenden Sie unter der Annahme, Ersatzschlüssel:

  1. für jede durchsuchbare Tabelle eine Ansicht erstellen, die Primärschlüsselspalte davon hat Tabelle, der Name der Tabelle und eine Verkettung aller durchsuchbaren Felder in dieser Tabelle.
  2. erstellen Sie einen funktionalen GIN oder GiST-Index auf dem zugrunde liegenden über die to_tsvector() der genau gleichen Verkettung.
  3. Erstellen Sie eine UNION ALL für alle Ansichten, um die durchsuchbare Ansicht zu erstellen.

Danach können Sie wie folgt die Suche machen:

SELECT id, table_name, ts_rank_cd(body, query) AS rank 
    FROM search_view, to_tsquery('search&words') query 
    WHERE query @@ body 
    ORDER BY rank DESC 
    LIMIT 10; 
7

Warum eine Ansicht nicht schaffen, die eine Vereinigung der Tabellen ist, die die Spalten, die Sie auf die Suche in einem wollen aggregiert und dann auf dieser aggregierten Spalte gesucht?

Man könnte so etwas tun:

select 'tenants:' + ltrim(str(t.Id)), <shared fields> from Tenants as t union 
select 'landlords:' + ltrim(str(l.Id)), <shared fields> from Tenants as l union 
... 

Diese gewisse Logik erfordert vom Client eingebettet werden abfragt; es muss wissen, wie man den Schlüssel herstellt, nach dem es sucht, um auf einem einzelnen Feld zu suchen.

Das heißt, es ist wahrscheinlich besser, wenn Sie nur eine separate Spalte haben, die einen "Typ" -Wert (zB Vermieter, Mieter) enthält und dann sowohl den Typ als auch die ID filtert, da es rechnerisch weniger teuer ist (und kann besser optimiert werden).

+2

Upvoting die unerklärliche und eigentümlich downvote zu kompensieren - diese Antwort, während prägnant, stellt eine durchaus vernünftige Idee (natürlich, dass auch sehen für die aktuellen Tabellen Primärschlüssel haben und diese Schlüssel sollten verschiedene, so dass die Identifizierung, welche Tabellen die verschiedenen gehalten werden Suchtreffer kamen von ist einfach). –

+1

Sie können einen konstanten und eindeutigen Wert in die Unterabfragen der Union einfügen, um eindeutige PKs zu vermeiden. –

1

Sie sollten in Ordnung sein, und es gibt wirklich keine andere gute (einfache) Möglichkeit, dies zu tun. Stellen Sie jedoch sicher, dass die Felder, nach denen Sie suchen, ordnungsgemäß indiziert sind.

4

Sie möchten the built-in full text search oder ein separates Produkt wie Lucene verwenden. Dies ist optimiert für unstrukturierte Suchen über heterogene Daten.

Vergessen Sie auch nicht, dass normale Indizes nicht für something LIKE '%...%' verwendet werden können. Mit einer Volltext-Suchmaschine können auch effiziente Teilstringsuchen durchgeführt werden.