Продолжая идею Измаила, это не окончательное решение, но я думаю, что это хороший способ начать.
Для начала нам нужно получить список слов, которые были получены с помощью полнотекстового движка:
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'
Уже многое можно расширить, например, шаблон поиска довольно прост; также, возможно, есть лучшие способы отфильтровать слова, которые вам не нужны, но, по крайней мере, он дает вам список основных слов и т. д., которые будут сопоставлены с полнотекстовым поиском.
После того, как вы получите нужные вам результаты, вы можете использовать RegEx для анализа набора результатов (или, предпочтительно, только подмножество, чтобы ускорить его, хотя я еще не нашел хороший способ сделать это). Для этого я просто использую два цикла while и несколько временных таблиц и переменных:
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
Несколько заметок:
1. Вложенные циклы while, вероятно, не самый эффективный способ сделать это, однако больше ничего не приходит на ум. Если бы я использовал курсоры, это было бы одно и то же?
2. @FirstSearchWord
здесь относится к первому экземпляру в тексте одного из оригинальных поисковых слов, поэтому, по сути, заменяемый текст будет только в кратком изложении. Опять же, это довольно простой метод, какой-то алгоритм поиска текстового кластера, вероятно, пригодится.
3. Чтобы получить RegEx, вам нужны пользовательские функции CLR.