Rozwijając ideę Ismaela, nie jest to ostateczne rozwiązanie, ale myślę, że to dobry sposób na rozpoczęcie.
Najpierw musimy uzyskać listę słów, które zostały pobrane za pomocą silnika pełnotekstowego:
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'
Jest już sporo rzeczy, które można rozwinąć, na przykład wzorzec wyszukiwania jest dość prosty; są też prawdopodobnie lepsze sposoby na odfiltrowanie słów, których nie potrzebujesz, ale przynajmniej daje to listę słów rdzeniowych itp., które można dopasować za pomocą wyszukiwania pełnotekstowego.
Po uzyskaniu potrzebnych wyników możesz użyć RegEx do przeanalizowania zestawu wyników (lub najlepiej tylko podzbioru, aby go przyspieszyć, chociaż nie wymyśliłem jeszcze dobrego sposobu, aby to zrobić). W tym celu po prostu używam dwóch pętli while i kilku tymczasowych tabel i zmiennych:
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
Kilka uwag:
1. Zagnieżdżone pętle while prawdopodobnie nie są najskuteczniejszym sposobem na zrobienie tego, jednak nic innego nie przychodzi do głowy. Gdybym miał używać kursorów, to w zasadzie byłoby to samo?
2. @FirstSearchWord
tutaj to odnosi się do pierwszego wystąpienia w tekście jednego z oryginalnych wyszukiwanych słów, więc zasadniczo tekst, który zastępujesz, będzie znajdować się tylko w streszczeniu. Ponownie, jest to dość podstawowa metoda, prawdopodobnie przydałby się jakiś algorytm wyszukiwania klastrów tekstu.
3. Aby uzyskać RegEx w pierwszej kolejności, potrzebujesz funkcji zdefiniowanych przez użytkownika CLR.