Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Como fazer realce de acertos de resultados de uma consulta de texto completo do SQL Server


Expandindo a ideia de Ismael, não é a solução final, mas acho que é uma boa maneira de começar.

Em primeiro lugar, precisamos obter a lista de palavras que foram recuperadas com o mecanismo 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'

Já há muito que se pode expandir, por exemplo, o padrão de pesquisa é bastante básico; provavelmente também há maneiras melhores de filtrar as palavras que você não precisa, mas pelo menos fornece uma lista de palavras-tronco etc. que seriam correspondidas pela pesquisa de texto completo.

Depois de obter os resultados necessários, você pode usar o RegEx para analisar o conjunto de resultados (ou, de preferência, apenas um subconjunto para acelerá-lo, embora eu ainda não tenha descoberto uma boa maneira de fazê-lo). Para isso eu simplesmente uso dois loops while e um monte de tabelas e variáveis ​​temporárias:
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

Várias notas:
1. Os loops while aninhados provavelmente não são a maneira mais eficiente de fazer isso, no entanto, nada mais vem à mente. Se eu fosse usar cursores, seria essencialmente a mesma coisa?
2. @FirstSearchWord aqui para refere-se à primeira instância no texto de uma das palavras de pesquisa originais, portanto, essencialmente, o texto que você está substituindo estará apenas no resumo. Novamente, é um método bastante básico, algum tipo de algoritmo de localização de cluster de texto provavelmente seria útil.
3. Para obter RegEx em primeiro lugar, você precisa de funções CLR definidas pelo usuário.