sql >> Databasteknik >  >> RDS >> Sqlserver

Hur man gör träff-markering av resultat från en SQL Server-fulltextfråga

Utvidgar Ishmaels idé, det är inte den slutgiltiga lösningen, men jag tror att det är ett bra sätt att börja.

Först måste vi få listan över ord som har hämtats med fulltextmotorn:

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'

Det finns redan ganska mycket man kan utöka, till exempel är sökmönstret ganska grundläggande; Det finns förmodligen också bättre sätt att filtrera bort de ord du inte behöver, men det ger dig åtminstone en lista över stamord etc. som skulle matchas av fulltextsökning.

När du har fått de resultat du behöver kan du använda RegEx för att analysera resultatuppsättningen (eller helst bara en delmängd för att påskynda det, även om jag ännu inte har kommit på ett bra sätt att göra det). För detta använder jag helt enkelt två while-loopar och ett gäng temporära tabeller och 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

Flera anteckningar:
1. Kapslade while-slingor är förmodligen inte det mest effektiva sättet att göra det på, men inget annat kommer att tänka på. Om jag skulle använda markörer, skulle det i princip vara samma sak?
2. @FirstSearchWord här refererar till den första instansen i texten av ett av de ursprungliga sökorden, så i huvudsak kommer texten du ersätter bara att finnas i sammanfattningen. Återigen, det är en ganska grundläggande metod, någon sorts algoritm för att hitta textkluster skulle förmodligen vara praktiskt.
3. För att få RegEx i första hand behöver du CLR användardefinierade funktioner.



  1. Hur tar jag en DISTINCT ON-underfråga som är sorterad efter en separat kolumn och gör den snabb?

  2. Tillfällig tabellpostgräns i SQL-server

  3. DB design:medlemmar tabell separat eller alla i en tabell?

  4. Hur man gör byggsystem för PostgreSQL