2008-10-14 7 views
12

Ich baue eine C#/ASP.NET App mit einem SQL-Backend. Ich habe die Frist eingehalten und meine Seiten fertiggestellt. Aus dem linken Bereich hat einer meiner Designer eine Volltextsuche auf einer meiner Seiten eingefügt. Meine "Suchen" bis zu diesem Punkt waren Filter, die ein Ergebnis um bestimmte Faktoren und Spaltenwerte eingrenzen konnten.Wie schwer ist es, Volltextsuche mit SQL Server zu integrieren?

Da ich auf Deadline bin (Sie wissen 3 Stunden Schlaf pro Nacht, an dem Punkt, wo ich wie etwas aussehe, das die Katze aß und kotzte), hatte ich erwartet, dass diese Seite sehr ähnlich zu anderen sein wird Ich versuche zu entscheiden, ob ich stinken soll oder nicht. Ich habe noch nie auf einer Seite eine Volltextsuche durchgeführt ... ist das ein Berg, den es zu besteigen gilt, oder gibt es eine einfache Lösung?

danke.

Antwort

27

Zunächst einmal, Sie Volltextsuche Indizierung aktiviert müssen auf den Produktionsservern, also wenn das nicht in Reichweite ist, wirst du damit nicht einverstanden sein.

Wenn dies jedoch bereits fertig ist, ist die Volltextsuche relativ einfach.

T-SQL verfügt über 4 Prädikate für Volltextsuche verwendet:

  • FREETEXT-
  • FREETEXTTABLE
  • ENTHÄLT
  • CONTAINS

FREETEXT- die einfachste ist, und kann getan werden, so:

SELECT UserName 
FROM Tbl_Users 
WHERE FREETEXT (UserName, 'bob') 

Results: 

JimBob 
Little Bobby Tables 

FREETEXTTABLE funktioniert genauso wie FreeTEXT, außer dass die Ergebnisse als Tabelle zurückgegeben werden.

Die wirkliche Macht der Volltextsuche T-SQL stammt aus der ENTHÄLT (und CONTAINS) Prädikat ... Dieser ist riesig, also werde ich einfach in der Anwendung einfügen:

CONTAINS 
    ({ column | * } , '<contains_search_condition>' 
    ) 

<contains_search_condition> ::= 
     { <simple_term> 
     | <prefix_term> 
     | <generation_term> 
     | <proximity_term> 
     | <weighted_term> 
     } 
     | { (<contains_search_condition>) 
     { AND | AND NOT | OR } <contains_search_condition> [ ...n ] 
     } 

<simple_term> ::= 
    word | " phrase " 

< prefix term > ::= 
    { "word * " | "phrase * " } 

<generation_term> ::= 
    FORMSOF (INFLECTIONAL , <simple_term> [ ,...n ]) 

<proximity_term> ::= 
    { <simple_term> | <prefix_term> } 
    { { NEAR | ~ } { <simple_term> | <prefix_term> } } [ ...n ] 

<weighted_term> ::= 
    ISABOUT 
     ({ { 
       <simple_term> 
       | <prefix_term> 
       | <generation_term> 
       | <proximity_term> 
       } 
      [ WEIGHT (weight_value) ] 
      } [ ,...n ] 
     ) 

Dies bedeutet, Sie können Abfragen schreiben wie:

SELECT UserName 
FROM Tbl_Users 
WHERE CONTAINS(UserName, '"little*" NEAR tables') 

Results: 

Little Bobby Tables 

Viel Glück :)

+4

Ich habe dies gewählt und nahm es als Antwort nicht nur, weil es eine große und detaillierte Antwort ist, sondern auch für die xkcd-Referenz. SIEG. –

0

"Wie schwer ist es" ist eine schwierige Frage zu beantworten. Zum Beispiel wird jemand, der es schon 10 mal gemacht hat, wahrscheinlich denken, dass es ein Kinderspiel ist. Alles, was ich wirklich sagen kann, ist, dass Sie es wahrscheinlich viel einfacher finden werden, wenn Sie etwas wie NLucene verwenden, anstatt selbst zu rollen.

2

Volltextsuche in SQL Server ist wirklich einfach, ein bisschen Konfiguration und ein wenig zwicken auf der Queryside und Sie sind gut zu gehen! Ich habe es für die Kunden gemacht, bevor sie in weniger als 20 Minuten, mit dem Prozess vertraut sein

Hier ist die 2008 MSDN article, gehen Links von dort zu den 2005-Versionen aus

2

ich dtSearch vor, um Dateien und Datenbanken der Suche nach Hinzufügen vollständigen Text verwendet haben, und ihre Sachen ist ziemlich billig und einfach t o benutzen.

Kurz gesagt, all das hinzufügen und SQL konfigurieren, Dieses Skript durchsucht alle Spalten in einer Datenbank und sagt Ihnen, welche Spalten die Werte enthalten, die Sie suchen.Ich weiß, es ist nicht die "richtige" Lösung, aber kann Ihnen etwas Zeit kaufen.

/*This script will find any text value in the database*/ 
/*Output will be directed to the Messages window. Don't forget to look there!!!*/ 

SET NOCOUNT ON 
DECLARE @valuetosearchfor varchar(128), @objectOwner varchar(64) 
SET @valuetosearchfor = '%staff%' --should be formatted as a like search 
SET @objectOwner = 'dbo' 

DECLARE @potentialcolumns TABLE (id int IDENTITY, sql varchar(4000)) 

INSERT INTO @potentialcolumns (sql) 
SELECT 
    ('if exists (select 1 from [' + 
    [tabs].[table_schema] + '].[' + 
    [tabs].[table_name] + 
    '] (NOLOCK) where [' + 
    [cols].[column_name] + 
    '] like ''' + @valuetosearchfor + ''') print ''SELECT * FROM [' + 
    [tabs].[table_schema] + '].[' + 
    [tabs].[table_name] + 
    '] (NOLOCK) WHERE [' + 
    [cols].[column_name] + 
    '] LIKE ''''' + @valuetosearchfor + '''''' + 
    '''') as 'sql' 
FROM information_schema.columns cols 
    INNER JOIN information_schema.tables tabs 
     ON cols.TABLE_CATALOG = tabs.TABLE_CATALOG 
      AND cols.TABLE_SCHEMA = tabs.TABLE_SCHEMA 
      AND cols.TABLE_NAME = tabs.TABLE_NAME 
WHERE cols.data_type IN ('char', 'varchar', 'nvchar', 'nvarchar','text','ntext') 
    AND tabs.table_schema = @objectOwner 
    AND tabs.TABLE_TYPE = 'BASE TABLE' 
ORDER BY tabs.table_catalog, tabs.table_name, cols.ordinal_position 

DECLARE @count int 
SET @count = (SELECT MAX(id) FROM @potentialcolumns) 
PRINT 'Found ' + CAST(@count as varchar) + ' potential columns.' 
PRINT 'Beginning scan...' 
PRINT '' 
PRINT 'These columns contain the values being searched for...' 
PRINT '' 
DECLARE @iterator int, @sql varchar(4000) 
SET @iterator = 1 
WHILE @iterator <= (SELECT Max(id) FROM @potentialcolumns) 
BEGIN 
    SET @sql = (SELECT [sql] FROM @potentialcolumns where [id] = @iterator) 
    IF (@sql IS NOT NULL) and (RTRIM(LTRIM(@sql)) <> '') 
    BEGIN 
     --SELECT @sql --use when checking sql output 
     EXEC (@sql) 
    END 
    SET @iterator = @iterator + 1 
END 

PRINT '' 
PRINT 'Scan completed' 
1

Ich war dort. Es funktioniert wie ein Zauber, bis Sie beginnen, Skalierbarkeit und erweiterte Suchfunktionalitäten wie Suche über mehrere Spalten mit jeweils unterschiedlichen Gewichtswerten zu betrachten.

Zum Beispiel ist die einzige Möglichkeit, über Titel Spalten und Zusammenfassung zu suchen ist eine berechnete Spalte mit SearchColumn = CONCAT(Title, Summary) und Index über SearchColumn zu haben. Gewichtung? SearchColumn = CONCAT(CONCAT(Title,Title), Summary) so etwas. ;) Filtern? Vergiss es.