Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Hervorheben von Treffern für Ergebnisse aus einer SQL Server-Volltextabfrage

Um Ishmaels Idee weiter auszubauen, ist es nicht die endgültige Lösung, aber ich denke, es ist ein guter Anfang.

Zuerst müssen wir die Liste der Wörter abrufen, die mit der Volltext-Engine abgerufen wurden:

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'

Es gibt bereits eine ganze Menge, die man erweitern kann, zum Beispiel ist das Suchmuster ziemlich einfach; außerdem gibt es wahrscheinlich bessere Möglichkeiten, die Wörter herauszufiltern, die Sie nicht benötigen, aber zumindest erhalten Sie eine Liste von Stammwörtern usw., die von der Volltextsuche gefunden würden.

Nachdem Sie die benötigten Ergebnisse erhalten haben, können Sie RegEx verwenden, um die Ergebnismenge zu analysieren (oder vorzugsweise nur eine Teilmenge, um sie zu beschleunigen, obwohl ich noch keinen guten Weg dafür gefunden habe). Dafür verwende ich einfach zwei While-Schleifen und eine Menge temporärer Tabellen und Variablen:

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

Einige Anmerkungen:
1. Verschachtelte While-Schleifen sind wahrscheinlich nicht die effizienteste Methode, aber mir fällt nichts anderes ein. Wenn ich Cursor verwenden würde, wäre es im Wesentlichen dasselbe?
2. @FirstSearchWord Hier auf bezieht sich auf das erste Vorkommen eines der ursprünglichen Suchwörter im Text, sodass der Text, den Sie ersetzen, im Wesentlichen nur in der Zusammenfassung enthalten sein wird. Auch hier handelt es sich um eine recht einfache Methode, eine Art Textcluster-Suchalgorithmus wäre wahrscheinlich praktisch.
3. Um überhaupt RegEx zu erhalten, benötigen Sie benutzerdefinierte CLR-Funktionen.