sql >> Database teknologi >  >> RDS >> Sqlserver

Sådan laver du hit-fremhævelse af resultater fra en SQL Server fuldtekstforespørgsel

Udvider Ishmaels idé, er det ikke den endelige løsning, men jeg synes, det er en god måde at starte på.

Først skal vi have listen over ord, der er blevet hentet med fuldtekstmotoren:

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'

Der er allerede ret meget, man kan uddybe, for eksempel er søgemønsteret ret grundlæggende; der er sikkert også bedre måder at filtrere de ord fra, du ikke har brug for, men det giver dig i det mindste en liste over stamord osv., som ville blive matchet ved fuldtekstsøgning.

Når du har fået de resultater, du har brug for, kan du bruge RegEx til at parse gennem resultatsættet (eller helst kun et undersæt for at fremskynde det, selvom jeg endnu ikke har fundet ud af en god måde at gøre det på). Til dette bruger jeg blot to while-løkker og en masse midlertidige tabel og variabler:

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

Flere bemærkninger:
1. Nested while-løkker er nok ikke den mest effektive måde at gøre det på, men intet andet kommer til at tænke på. Hvis jeg skulle bruge markører, ville det i det væsentlige være det samme?
2. @FirstSearchWord her refererer til den første instans i teksten af ​​et af de originale søgeord, så i det væsentlige vil den tekst, du erstatter, kun være i resuméet. Igen, det er en ganske grundlæggende metode, en form for tekstklyngefindingsalgoritme ville nok være praktisk.
3. For at få RegEx i første omgang skal du bruge CLR brugerdefinerede funktioner.



  1. PDO - lastInsertId() for indsæt forespørgsel med flere rækker

  2. Forskellen mellem int og int(2) datatyper i min sql

  3. CSV-kopi til Postgres med array af brugerdefineret type ved hjælp af JDBC

  4. Få kun næstsidste post - mysql-query