Pregunta

Contamos con una aplicación web que utiliza SQL Server 2008 como base de datos.Nuestros usuarios pueden realizar búsquedas de texto completo en columnas particulares de la base de datos.La funcionalidad de texto completo de SQL Server no parece admitir el resaltado de visitas.¿Necesitamos construirlo nosotros mismos o tal vez exista alguna biblioteca o conocimiento sobre cómo hacerlo?

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 traducirla.

¿Fue útil?

Solución

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

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 hay muchas cosas que podemos ampliar, por ejemplo, el patrón de búsqueda es bastante básico;Probablemente también haya mejores formas de filtrar las palabras que no necesitas, pero al menos te brinda una lista de palabras raíz, etc.que coincidiría con la búsqueda de texto completo.

Después de obtener los resultados que necesita, puede usar RegEx para analizar el 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 bucles while y un montón 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.Los bucles while anidados probablemente no sean la forma más eficiente de hacerlo, sin embargo, no se me ocurre nada más.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.Nuevamente, es un método bastante básico; probablemente sería útil algún tipo de algoritmo de búsqueda de grupos de texto.
3.Para obtener RegEx en primer lugar, necesita funciones CLR definidas por el usuario.

Otros consejos

Parece que podrías analizar el resultado del nuevo Procedimiento almacenado de SQL Server 2008 sys.dm_fts_parser y uso expresiones regulares, pero no lo he examinado demasiado de cerca.

Es posible que se esté perdiendo el sentido de la base de datos en este caso.Su trabajo es devolverle los datos que satisfagan las condiciones que usted les proporcionó.Creo que querrás implementar el resaltado probablemente usando expresiones regulares 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

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top