sql-server full-text-search highlighting hit-highlighting

Cómo hacer hit-highlighting de resultados de una consulta de texto completo de SQL Server



sql-server full-text-search (4)

Es posible que te pierdas el objetivo de la base de datos en esta instancia. Su trabajo es devolverle los datos que satisfagan las condiciones que le dio. Creo que querrás implementar el resaltado probablemente usando regex en tu control web.

Aquí hay algo que una búsqueda rápida revelaría.

http://www.dotnetjunkies.com/PrintContent.aspx?type=article&id=195E323C-78F3-4884-A5AA-3A1081AC3B35

Tenemos una aplicación web que usa SQL Server 2008 como base de datos. Nuestros usuarios pueden realizar búsquedas de texto completo en columnas particulares en la base de datos. La funcionalidad de texto completo de SQL Server no parece brindar soporte para el resaltado de visitas. ¿Necesitamos construir esto nosotros mismos o quizás hay alguna biblioteca o conocimiento acerca de cómo hacer esto?

Por cierto, la aplicación está escrita en C # por lo que una solución .Net sería ideal, pero no necesaria, ya que podríamos traducir.


Algunos detalles:

search_kiemeles=replace(lcase(search),"""","") do while not rs.eof ''The search result loop hirdetes=rs("hirdetes") data=RegExpValueA("([A-Za-zöüóőúéáűíÖÜÓŐÚÉÁŰÍ0-9]+)",search_kiemeles) ''Give back all the search words in an array, I need non-english characters also For i=0 to Ubound(data,1) hirdetes = RegExpReplace(hirdetes,"("&NoAccentRE(data(i))&")","<em>$1</em>") Next response.write hirdetes rs.movenext Loop ...

Funciones

''All Match to Array Function RegExpValueA(patrn, strng) Dim regEx Set regEx = New RegExp '' Create a regular expression. regEx.IgnoreCase = True '' Set case insensitivity. regEx.Global = True Dim Match, Matches, RetStr Dim data() Dim count count = 0 Redim data(-1) ''VBSCript Ubound array bug workaround if isnull(strng) or strng="" then RegExpValueA = data exit function end if regEx.Pattern = patrn '' Set pattern. Set Matches = regEx.Execute(strng) '' Execute search. For Each Match in Matches '' Iterate Matches collection. count = count + 1 Redim Preserve data(count-1) data(count-1) = Match.Value Next set regEx = nothing RegExpValueA = data End Function ''Replace non-english chars Function NoAccentRE(accent_string) NoAccentRE=accent_string NoAccentRE=Replace(NoAccentRE,"a","§") NoAccentRE=Replace(NoAccentRE,"á","§") NoAccentRE=Replace(NoAccentRE,"§","[aá]") NoAccentRE=Replace(NoAccentRE,"e","§") NoAccentRE=Replace(NoAccentRE,"é","§") NoAccentRE=Replace(NoAccentRE,"§","[eé]") NoAccentRE=Replace(NoAccentRE,"i","§") NoAccentRE=Replace(NoAccentRE,"í","§") NoAccentRE=Replace(NoAccentRE,"§","[ií]") NoAccentRE=Replace(NoAccentRE,"o","§") NoAccentRE=Replace(NoAccentRE,"ó","§") NoAccentRE=Replace(NoAccentRE,"ö","§") NoAccentRE=Replace(NoAccentRE,"ő","§") NoAccentRE=Replace(NoAccentRE,"§","[oóöő]") NoAccentRE=Replace(NoAccentRE,"u","§") NoAccentRE=Replace(NoAccentRE,"ú","§") NoAccentRE=Replace(NoAccentRE,"ü","§") NoAccentRE=Replace(NoAccentRE,"ű","§") NoAccentRE=Replace(NoAccentRE,"§","[uúüű]") end function



Ampliando la idea de Ishmael, no es la solución final, pero creo que es una buena manera de comenzar.

En primer lugar, necesitamos obtener la lista de palabras que se han recuperado con el motor de texto completo:

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''

Ya se puede expandir bastante, por ejemplo, el patrón de búsqueda es bastante básico; también hay probablemente mejores formas de filtrar las palabras que no necesita, pero al menos le da una lista de palabras clave, etc. que se correspondería con la búsqueda de texto completo.

Después de obtener los resultados que necesita, puede usar RegEx para analizar a través del conjunto de resultados (o preferiblemente solo un subconjunto para acelerarlo, aunque todavía no he descubierto una buena manera de hacerlo). Para esto, simplemente uso dos ciclos while y un grupo de tablas y variables temporales:

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

Varias notas:
1. Anidado, mientras que los bucles probablemente no son la forma más eficiente de hacerlo, sin embargo, nada más viene a la mente. Si tuviera que usar cursores, ¿sería esencialmente lo mismo?
2. @FirstSearchWord aquí se refiere a la primera instancia en el texto de una de las palabras de búsqueda originales, por lo que esencialmente el texto que está reemplazando solo estará en el resumen. De nuevo, es un método bastante básico, algún tipo de algoritmo de búsqueda de clústeres de texto probablemente sería útil.
3. Para obtener RegEx en primer lugar, necesita funciones CLR definidas por el usuario.