sql >> Base de Datos >  >> RDS >> Sqlserver

Cómo resaltar los resultados de una consulta de texto completo de SQL Server

Ampliando la idea de Ishmael, no es la solución final, pero creo que es una buena forma de empezar.

En primer lugar, necesitamos obtener la lista de palabras que se han recuperado con el motor de texto completo:

declare @SearchPattern nvarchar(1000) = 'FORMSOF (INFLECTIONAL, " ' + @SearchString + ' ")' 
declare @SearchWords table (Word varchar(100), Expansion_type int)
insert into @SearchWords
select distinct display_term, expansion_type
from sys.dm_fts_parser(@SearchPattern, 1033, 0, 0)
where special_term = 'Exact Match'

Ya hay mucho que se puede ampliar, por ejemplo, el patrón de búsqueda es bastante básico; También hay probablemente mejores formas de filtrar las palabras que no necesita, pero al menos le da una lista de palabras raíz, etc. que coincidirían con la búsqueda de texto completo.

Después de obtener los resultados que necesita, puede usar RegEx para analizar el conjunto de resultados (o preferiblemente solo un subconjunto para acelerarlo, aunque todavía no he descubierto una buena manera de hacerlo). Para esto, simplemente uso dos bucles while y un montón de tablas y variables temporales:

declare @FinalResults table 
while (select COUNT(*) from @PrelimResults) > 0
begin
    select top 1 @CurrID = [UID], @Text = Text from @PrelimResults
    declare @TextLength int = LEN(@Text )
    declare @IndexOfDot int = CHARINDEX('.', REVERSE(@Text ), @TextLength - dbo.RegExIndexOf(@Text, '\b' + @FirstSearchWord + '\b') + 1)
    set @Text = SUBSTRING(@Text, case @IndexOfDot when 0 then 0 else @TextLength - @IndexOfDot + 3 end, 300)

    while (select COUNT(*) from @TempSearchWords) > 0
    begin
        select top 1 @CurrWord = Word from @TempSearchWords
        set @Text = dbo.RegExReplace(@Text, '\b' + @CurrWord + '\b',  '<b>' + SUBSTRING(@Text, dbo.RegExIndexOf(@Text, '\b' + @CurrWord + '\b'), LEN(@CurrWord) + 1) + '</b>')
        delete from @TempSearchWords where Word = @CurrWord
    end

    insert into @FinalResults
    select * from @PrelimResults where [UID] = @CurrID
    delete from @PrelimResults where [UID] = @CurrID
end

Varias notas:
1. Los bucles while anidados probablemente no sean la forma más eficiente de hacerlo, sin embargo, no se me ocurre nada más. Si tuviera que usar cursores, ¿sería esencialmente lo mismo?
2. @FirstSearchWord aquí a se refiere a la primera instancia en el texto de una de las palabras de búsqueda originales, por lo que esencialmente el texto que está reemplazando solo estará en el resumen. Una vez más, es un método bastante básico, probablemente sería útil algún tipo de algoritmo de búsqueda de grupos de texto.
3. Para obtener RegEx en primer lugar, necesita las funciones definidas por el usuario de CLR.