Quanto è difficile incorporare la ricerca full-text con SQL Server?
-
03-07-2019 - |
Domanda
Sto creando un'app C # / ASP.NET con un back-end SQL. Sono in scadenza e sto finendo le mie pagine, fuori dal campo di sinistra uno dei miei designer ha incorporato una ricerca a testo integrale su una delle mie pagine. Le mie ricerche "quotate" fino a questo punto sono stati filtrati, essendo in grado di restringere un set di risultati per determinati fattori e valori di colonna.
Essendo che sono in scadenza (sai 3 ore di sonno a notte, nel punto in cui sembro qualcosa che il gatto ha mangiato e vomitato), mi aspettavo che questa pagina fosse molto simile agli altri e io Sto cercando di decidere se fare o meno una puzza. Non ho mai fatto una ricerca a testo integrale su una pagina prima ... è una montagna da scalare o c'è una soluzione semplice?
grazie.
Soluzione
Prima di tutto, devi abilitare l'indicizzazione della ricerca full-text sui server di produzione, quindi se non rientra nell'ambito, non vorrai andare con questo.
Tuttavia, se è già pronto, la ricerca full-text è relativamente semplice.
T-SQL ha 4 predicati usati per la ricerca full-text:
- FREETEXT
- FREETEXTTABLE
- contiene
- CONTAINSTABLE
FREETEXT è il più semplice e può essere fatto in questo modo:
SELECT UserName
FROM Tbl_Users
WHERE FREETEXT (UserName, 'bob' )
Results:
JimBob
Little Bobby Tables
FREETEXTTABLE funziona come FreeTEXT, tranne per il fatto che restituisce i risultati come tabella.
Il vero potere della ricerca full-text di T-SQL proviene dal predicato CONTAINS (e CONTAINSTABLE) ... Questo è enorme, quindi incollerò il suo utilizzo in:
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 ]
)
Ciò significa che puoi scrivere query come:
SELECT UserName
FROM Tbl_Users
WHERE CONTAINS(UserName, '"little*" NEAR tables')
Results:
Little Bobby Tables
Buona fortuna :)
Altri suggerimenti
La ricerca full-text in SQL Server è davvero semplice, un po 'di configurazione e una leggera modifica in queryside e sei a posto! L'ho fatto per i clienti in meno di 20 minuti prima, conoscendo il processo
Ecco articolo MSDN 2008 , i collegamenti vanno a le versioni del 2005 da lì
Ho già usato dtSearch per aggiungere ricerche di testo completo a file e database, e il loro materiale è piuttosto economico e facile da usare.
A parte l'aggiunta di tutto ciò e la configurazione di SQL, questo script cercherà in tutte le colonne di un database e ti dirà quali colonne contengono i valori che stai cercando. So che non è il "corretto" soluzione, ma potrebbe farti guadagnare un po 'di tempo.
/*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'
Sono stato lì. Funziona come un incantesimo fino a quando non inizi a considerare la scalabilità e le funzionalità di ricerca avanzata come la ricerca su più colonne con valori di peso diversi per ognuno.
Ad esempio, l'unico modo per cercare tra le colonne Titolo e Riepilogo è disporre di una colonna calcolata con SearchColumn = CONCAT (Titolo, Riepilogo) e indicizza su
SearchColumn
. Ponderazione? SearchColumn = CONCAT (CONCAT (Title, Title), Summary)
qualcosa del genere. ;) Filtro? Dimenticalo.
" Quanto è difficile " è una domanda difficile a cui rispondere. Ad esempio, qualcuno che lo ha già fatto 10 volte probabilmente calcolerà che è un gioco da ragazzi. Tutto quello che posso davvero dire è che probabilmente lo troverai molto più semplice se usi qualcosa come NLucene piuttosto che lanciare il tuo.