代码之家  ›  专栏  ›  技术社区  ›  Phil Haselden

如何突出显示SQL Server全文查询的结果

  •  8
  • Phil Haselden  · 技术社区  · 17 年前

    我们有一个使用SQL Server 2008作为数据库的Web应用程序。我们的用户能够对数据库中的特定列进行全文搜索。SQL Server的全文功能似乎不支持突出显示。我们是否需要自己构建它,或者是否有一些关于如何构建它的库或知识?

    顺便说一下,应用程序是用C语言编写的,因此.NET解决方案是理想的,但不是必要的,因为我们可以翻译。

    4 回复  |  直到 11 年前
        1
  •  3
  •   Shagglez    15 年前

    扩展伊士梅尔的想法,这不是最终的解决方案,但我认为这是一个很好的开始方式。

    首先,我们需要获取全文引擎检索到的单词列表:

    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 这里的to指的是一个原始搜索词的文本中的第一个实例,因此从本质上讲,您要替换的文本只会出现在摘要中。同样,这是一个非常基本的方法,某种文本簇查找算法可能会很方便。
    三。首先,要获得regex,需要clr用户定义函数。

        2
  •  3
  •   Ishmael    17 年前

    看起来您可以解析新的 SQL Server 2008 stored procedure sys.dm_fts_parser 使用regex,但我没有仔细观察过。

        3
  •  1
  •   WIDBA    17 年前

    您可能缺少此实例中的数据库点。它的工作是将满足您提供的条件的数据返回给您。我认为您可能希望在Web控件中使用regex实现突出显示。

    这是一个快速搜索可以揭示的信息。

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

        4
  •  1
  •   xnagyg    17 年前

    一些细节:

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

    功能

    '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
    
    推荐文章