5 Stimmen

SQL Server Volltextsuche - viele-zu-viele-Beziehung

Ich arbeite an einem Projekt mit SQL Server 2008, bei dem ich glaube, dass die Volltextsuche der beste Weg ist. Ich habe so viel wie möglich darüber gelesen und verstehe im Großen und Ganzen, wie man es für eine einzelne Tabelle einrichtet. Allerdings bin ich mir nicht ganz sicher, wie ich es mit meinem Szenario einrichte - stell dir die folgende Tabellenstruktur vor:

Buch

- Id
- Titel
- Beschreibung

BuchAutor

- BuchId
- AutorId

Autor

- Id
- Name

Wie du sehen kannst, enthält die Datenbank eine Tabelle mit Büchern, und jedes Buch kann keinen, einen oder mehrere Autoren haben. Jeder Autor kann auch keinen, einen oder mehrere Bücher haben - d.h. die Tabellen Buch und Autor haben eine Many-to-Many-Beziehung, die mit der Verknüpfungstabelle BuchAutor behandelt wird.

Was ich zu diesem Zeitpunkt erreichen möchte, ist ein Suchwerkzeug, um Bücher zu finden, die auf einen Suchbegriff basieren, den der Benutzer angibt. Wenn der Benutzer z.B. Brown eingibt, möchte ich alle Bücher finden, bei denen eine der folgenden Spalten das Wort Brown enthält:

Buch.Titel
Buch.Beschreibung
Autor.Name

Im Wesentlichen möchte ich eine Ergebnismenge von Büchern, einschließlich des Buches mit dem Titel Brown Bear und der Bücher, die von Autor Dan Brown geschrieben wurden. Wenn es irgendwelche Vorschläge gibt, wie ich dies einrichten sollte, wäre ich wirklich dankbar für Ihren Beitrag!

(als Nebenbemerkung, sobald ich dieses Filtern zum Laufen gebracht habe, müsste das Abfrageergebnis auch sortierbar und in Seiten unterteilt sein, die über @SortOrder, @PageIndex und @PageSize an eine gespeicherte Prozedur übergeben werden - aber ich denke, das könnte eine separate Frage sein!)

0 Stimmen

Warum nehmen Sie an, dass die Volltextsuche hier eine angemessene Lösung ist? Das sieht für mich völlig wie ein normaler Datenbank-Design aus.

0 Stimmen

0 Stimmen

@TomTom Die Suche nach "Brown" wie oben ist nur ein vereinfachtes Beispiel dessen, was ich erreichen möchte. Ich muss in der Lage sein, nach x Anzahl von Wörtern zu suchen, und mit LIKE wird das nicht funktionieren. Außerdem möchten wir in Zukunft in der Lage sein, Zeilen zu finden, die fast übereinstimmen, und dafür wird eine Volltextsuche benötigt (soweit ich weiß).

3voto

Joe Alfano Punkte 9859

Ein CONTAINS-Prädikat kann eine Liste von Spalten als erstes Argument zum Suchen annehmen; jedoch müssen diese Spalten aus einer einzigen Tabelle stammen. Sie haben ein paar Optionen, um diese Einschränkung zu umgehen. Eine Möglichkeit besteht darin, zwei separate Suchvorgänge durchzuführen, einen in jeder Tabelle, und dann die Ergebnisse zu verbinden.

select Id, Title from Book where contains([Description], 'brown')
union
select b.Id, b.Title
    from Book b inner join BookAuthor ba on b.Id = ba.BookId
        inner join Author a on a.Id=ba.AuthorId
    where contains([Name], 'brown')

Eine andere Möglichkeit besteht darin, von der Tatsache zu profitieren, dass FTS-Indizes auf indizierten Ansichten erstellt werden können. Erstellen Sie dazu eine indizierte Ansicht, die sowohl das Feld Title aus der Tabelle Book als auch das Feld Name aus der Tabelle Author enthält, und erstellen Sie dann einen FTS-Index auf beiden Spalten in der Ansicht. Dann können Sie Abfragen gegen diese Ansicht wie folgt schreiben:

select BookId, Title from vw_BooksAndAuthors 
where contains(([Description], [Name]), 'brown')

0 Stimmen

Vielen Dank für die Vorschläge Joe! #1 Ich sehe auf jeden Fall, dass dies die richtigen Ergebnisse liefern würde - hast du eine Vorstellung davon, wie sich die Leistung durch zwei Abfragen und ein Union auswirkt? Angenommen, ein Buch hat sowohl eine Beschreibung, die der Suche entspricht, als auch 5 separate Autoren, die übereinstimmen - dasselbe Buch würde 6 Mal gefunden, bevor sie mit der Union-Anweisung "zusammengeführt" werden.

0 Stimmen

Richtig, die Leistung von zwei Abfragen und einer Vereinigung ist definitiv schlimmer als die einer einzelnen Abfrage. Es gibt einige Dinge, die Sie aus Leistungsgründen in Betracht ziehen sollten, aber bevor Sie Zeit investieren, sollten Sie zunächst feststellen, dass die Leistung in Ihrer App tatsächlich ein Problem darstellt, und keine Zeit mit vorzeitiger Optimierung verschwenden. Wenn Sie die Leistung optimieren möchten, könnten Sie einen Job haben, der regelmäßig läuft und den Inhalt der Buch- und Autorentabellen in eine einzelne denormalisierte Tabelle aggregiert, und dann die einzelne denormalisierte Tabelle abfragen.

0 Stimmen

Ja, ich habe auch über diese Option nachgedacht, eine BookIndex-Tabelle zu haben, die die BookId und eine/eine Reihe von zusätzlichen Spalten enthält, die alle relevanten suchbaren Informationen wie den Titel, die Beschreibung und den Namen jedes Autors in einer einzigen Zeile in dieser Tabelle zusammengefasst haben. Dann diesen in eine Volltextindex umwandeln und ihn mit der Book-Tabelle verbinden, wenn Sie suchen. Ich denke, ich werde Ihren ersten Vorschlag oben mit der Vereinigung versuchen, aber wenn die Leistung ein Problem wird, werde ich stattdessen diesen Weg gehen. Vielen Dank für Ihren Beitrag!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X