SQL Server全文搜索与回退完全匹配

时间:2013-04-21 11:13:53

标签: sql-server-2008 full-text-search contains exact-match

首先,似乎无法使用全文搜索获得完全匹配。当使用全文搜索方法时,这似乎是一个高度讨论的问题,并且有许多不同的解决方案来实现期望的结果,但是大多数看起来非常低效。由于数据库的数量,我不得不使用全文搜索,我最近不得不实施其中一种解决方案以获得更准确的结果。

我无法使用全文搜索的排名结果,因为它的工作原理。例如,如果您搜索了一部名为Toy Story的电影,并且还有一部名为The Story Behind Toy Story的电影会出现,而不是完全匹配,因为它找到了Story字两次{{1} }}

我跟踪自己的排名,每当用户访问记录数量增加时,我称之为“人气”。我使用此数据点来对结果进行加权,以帮助确定用户可能正在查找的内容。

我还有一个问题,有时需要回到LIKE搜索而不返回完全匹配。即搜索Toy应该返回Goonies(最受欢迎的结果)

所以这是我目前存储过程的一个例子:

The Goonies

这个存储过程每分钟执行大约5000次,并且疯狂到不会让我的服务器瘫痪。但我真的想知道是否有更有效的方法呢?感谢。

4 个答案:

答案 0 :(得分:5)

您应该使用全文搜索CONTAINSTABLE来查找前100个(可能是200个)候选结果,然后使用您自己的条件对您找到的结果进行排序。

听起来你想ORDER BY

  1. 短语(=
  2. 的完全匹配
  3. 完全匹配的词组(LIKE
  4. Popularity
  5. 的值更高
  6. Rank
  7. 中的CONTAINSTABLE

    但是你可以按照自己喜欢的顺序玩弄它。

    在SQL中看起来像:

    DECLARE @title varchar(255)
    SET @title = '"Toy Story"'
    --need to remove quotes from parameter for LIKE search
    DECLARE @title2 varchar(255)
    SET @title2 = REPLACE(@title, '"', '')
    
    SELECT
        m.ID,
        m.title,
        m.Popularity,
        k.Rank
    FROM Movies m
    INNER JOIN CONTAINSTABLE(Movies, title, @title, 100) as [k]
        ON m.ID = k.[Key]
    ORDER BY 
      CASE WHEN m.title = @title2 THEN 0 ELSE 1 END,
      CASE WHEN m.title LIKE @title2 THEN 0 ELSE 1 END,
      m.popularity desc,
      k.rank
    

    请参阅SQLFiddle

答案 1 :(得分:2)

这将为您提供包含确切短语“玩具总动员”的电影,按其受欢迎程度排序。

SELECT
    m.[ID],
    m.[Popularity],
    k.[Rank]
FROM [dbo].[Movies] m
INNER JOIN CONTAINSTABLE([dbo].[Movies], [Title], N'"Toy Story"') as [k]
    ON m.[ID] = k.[Key]
ORDER BY m.[Popularity]

注意如果您搜索“The Goonies”,上面的内容也会给你“The Goonies Return”。

答案 2 :(得分:0)

如果感觉到你并不喜欢全文搜索的模糊部分,但你确实喜欢表演部分。

这可能是一条路径:如果你坚持在加权匹配之前获得完全匹配,你可以尝试哈希值。例如'玩具总动员' - >带到小写 - >玩具故事 - >哈希到4de2gs5sa(你喜欢的任何哈希)并在哈希上执行搜索。

答案 3 :(得分:0)

在Oracle中,我使用UTL_MATCH用于类似目的。 (http://docs.oracle.com/cd/E11882_01/appdev.112/e25788/u_match.htm

例如,即使使用Jaro Winkler算法,如果比较表1和表2中的标题列,也可能需要一段时间,如果部分加入2个表,则可以提高性能。在某些情况下,我在表1中将人名与使用Jaro Winkler的表2进行了比较,但结果不仅仅限于特定的Jaro Winkler阈值,还包括第一个字母相同的2个表之间的名称。例如,我会使用Jaro Winkler将Albert与Aden,Alfonzo和Alberto进行比较,而不是使用Albert和Frank(限制算法需要使用的情况的数量)。

Jaro Winkler也可能适合电影片头。虽然你使用的是SQL服务器(不能使用utl_match包),但看起来有一个名为“SimMetrics”的免费库,其中包含Jaro Winkler算法以及其他字符串比较指标。您可以在此处找到相关详情和说明:http://anastasiosyal.com/POST/2009/01/11/18.ASPX?#simmetrics