首先,似乎无法使用全文搜索获得完全匹配。当使用全文搜索方法时,这似乎是一个高度讨论的问题,并且有许多不同的解决方案来实现期望的结果,但是大多数看起来非常低效。由于数据库的数量,我不得不使用全文搜索,我最近不得不实施其中一种解决方案以获得更准确的结果。
我无法使用全文搜索的排名结果,因为它的工作原理。例如,如果您搜索了一部名为Toy Story
的电影,并且还有一部名为The Story Behind Toy Story
的电影会出现,而不是完全匹配,因为它找到了Story
字两次{{1} }}
我跟踪自己的排名,每当用户访问记录数量增加时,我称之为“人气”。我使用此数据点来对结果进行加权,以帮助确定用户可能正在查找的内容。
我还有一个问题,有时需要回到LIKE搜索而不返回完全匹配。即搜索Toy
应该返回Goonies
(最受欢迎的结果)
所以这是我目前存储过程的一个例子:
The Goonies
这个存储过程每分钟执行大约5000次,并且疯狂到不会让我的服务器瘫痪。但我真的想知道是否有更有效的方法呢?感谢。
答案 0 :(得分:5)
您应该使用全文搜索CONTAINSTABLE
来查找前100个(可能是200个)候选结果,然后使用您自己的条件对您找到的结果进行排序。
听起来你想ORDER BY
=
)LIKE
)Popularity
列Rank
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