Pergunta

Temos uma aplicação web que usa o SQL Server 2008 como banco de dados.Nossos usuários podem fazer pesquisas de texto completo em colunas específicas do banco de dados.A funcionalidade de texto completo do SQL Server não parece fornecer suporte para destaque de ocorrências.Precisamos construir isso nós mesmos ou talvez haja alguma biblioteca ou conhecimento sobre como fazer isso?

Aliás, o aplicativo é escrito em C#, portanto, uma solução .Net seria ideal, mas não necessária, pois poderíamos traduzir.

Foi útil?

Solução

Expandindo a ideia de Ismael, não é a solução final, mas acho que é uma boa maneira de começar.

Primeiramente precisamos obter a lista de palavras que foram recuperadas com o mecanismo 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'

Já há bastante coisa que pode ser expandida, por exemplo, o padrão de pesquisa é bastante básico;provavelmente também existem maneiras melhores de filtrar as palavras que você não precisa, mas pelo menos fornece uma lista de palavras-tronco, etc.que seria correspondido pela pesquisa de texto completo.

Depois de obter os resultados necessários, você pode usar o RegEx para analisar o conjunto de resultados (ou, de preferência, apenas um subconjunto para acelerá-lo, embora eu ainda não tenha descoberto uma boa maneira de fazer isso).Para isso eu simplesmente uso dois loops while e um monte de tabelas e variáveis ​​temporárias:

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

Várias notas:
1.Loops while aninhados provavelmente não são a maneira mais eficiente de fazer isso, mas nada mais vem à mente.Se eu usasse cursores, seria essencialmente a mesma coisa?
2. @FirstSearchWord aqui, refere-se à primeira instância no texto de uma das palavras de pesquisa originais, portanto, essencialmente, o texto que você está substituindo estará apenas no resumo.Novamente, é um método bastante básico, algum tipo de algoritmo de localização de cluster de texto provavelmente seria útil.
3.Para obter RegEx em primeiro lugar, você precisa de funções CLR definidas pelo usuário.

Outras dicas

Parece que você poderia analisar a saída do novo Procedimento armazenado do SQL Server 2008 sys.dm_fts_parser e usar regex, mas não olhei muito de perto.

Você pode estar perdendo o objetivo do banco de dados nesta instância.Sua função é retornar os dados que satisfaçam as condições que você forneceu.Acho que você desejará implementar o destaque provavelmente usando regex em seu controle web.

Aqui está algo que uma pesquisa rápida revelaria.

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

Alguns detalhes:

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

Funções

'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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top