Pregunta

Estoy creando una aplicación C # / ASP.NET con un servidor SQL. Estoy en la fecha límite y terminando mis páginas, fuera del campo izquierdo, uno de mis diseñadores incorporó una búsqueda de texto completo en una de mis páginas. Mis " búsquedas " hasta este punto, se han filtrado, pudiendo reducir un conjunto de resultados por ciertos factores y valores de columna.

Siendo que estoy en la fecha límite (sabes 3 horas de sueño por noche, en el punto en el que me veo como algo que el gato comió y vomitó), esperaba que esta página fuera muy similar a las otras y yo Estoy intentando decidir si apestar o no. Nunca he hecho una búsqueda de texto completo en una página antes ... ¿Es esta una montaña para escalar o hay una solución simple?

gracias.

¿Fue útil?

Solución

En primer lugar, debe habilitar la indexación de búsqueda de texto completo en los servidores de producción, por lo que si eso no está dentro del alcance, no querrá continuar con esto.

Sin embargo, si eso ya está listo, la búsqueda de texto completo es relativamente simple.

T-SQL tiene 4 predicados utilizados para la búsqueda de texto completo:

  • FREETEXT
  • FREETEXTTABLE
  • CONTIENE
  • CONTAINSTABLE

FREETEXT es el más simple, y se puede hacer así:

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

Results:

JimBob
Little Bobby Tables

FREETEXTTABLE funciona igual que FreeTEXT, excepto que devuelve los resultados como una tabla.

El verdadero poder de la búsqueda de texto completo de T-SQL proviene del predicado CONTAINS (y CONTAINSTABLE) ... Este es enorme, así que pegaré su uso en:

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

Esto significa que puede escribir consultas como:

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

Results:

Little Bobby Tables

Buena suerte :)

Otros consejos

La búsqueda de texto completo en SQL Server es realmente fácil, un poco de configuración y un ligero ajuste en el lado de la consulta, ¡y listo! Lo he hecho para clientes en menos de 20 minutos antes, familiarizado con el proceso

Aquí está el artículo de MSDN 2008 , los enlaces salen a las versiones de 2005 a partir de ahí

He usado dtSearch antes para agregar búsquedas de texto completo a archivos y bases de datos, y sus cosas son bastante baratas y fáciles de usar.

A falta de agregar todo eso y configurar SQL, este script buscará en todas las columnas de una base de datos y le dirá qué columnas contienen los valores que está buscando. Sé que no es el "correcto" solución, pero puede comprarte algo de tiempo.

/*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'

He estado allí. Funciona a las mil maravillas hasta que empiezas a considerar la escalabilidad y las funcionalidades de búsqueda avanzada, como buscar en varias columnas, dando a cada uno valores de peso diferentes.

Por ejemplo, la única forma de buscar en las columnas Título y Resumen es tener una columna calculada con SearchColumn = CONCAT (Título, Resumen) e indexe sobre SearchColumn . Ponderación? SearchColumn = CONCAT (CONCAT (Título, Título), Resumen) algo así. ;) ¿Filtrado? Olvídate de eso.

" ¿Qué tan difícil es " Es una pregunta difícil de responder. Por ejemplo, alguien que ya lo ha hecho 10 veces probablemente considerará que es fácil. Todo lo que realmente puedo decir es que es probable que lo encuentre mucho más fácil si usa algo como NLucene en lugar de rodar el tuyo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top