【发布时间】:2012-05-17 14:23:00
【问题描述】:
我正在实现一个自动完成功能,它允许用户输入部分文本,然后与表中的 4 个不同列进行匹配。这是一个基本示例:
+------------+-----------+--------+-----------------+
| first_name | last_name | login | email |
+------------+-----------+--------+-----------------+
| John | Smith | jsmith | jsmith@foo.bar |
| Johnny | Ringo | ringo | ringer@hmm.okay |
| Bob | Jones | bjones | j1234@xyz.abc |
| Jane | Doe | doej | doedoe@blah.umm |
+------------+-----------+--------+-----------------+
当用户输入“jo”时,我想匹配该表中的记录,其中这四列中至少有一个与模式“jo%”匹配。对于此示例,由于它们的 first_name 列值,只有前两个会匹配。如果搜索是“js”,那么由于其 login 和 email 列值,只有第一条记录会匹配。等等。我还想返回按相似度排序的结果,其中第一个结果是“最接近的匹配”,依此类推(标准自动完成行为)。
我目前一直在尝试使用UTL_MATCH 和产生以下查询的代码来解决这个问题:
SELECT first_name,
last_name,
login,
email,
( utl_match.jaro_winkler_similarity(first_name, 'js')
+ utl_match.jaro_winkler_similarity(last_name, 'js')
+ utl_match.jaro_winkler_similarity(login, 'js')
+ utl_match.jaro_winkler_similarity(email, 'js')) similarity
FROM users
WHERE LOWER(first_name) LIKE LOWER('js%')
OR LOWER(last_name) LIKE LOWER('js%')
OR LOWER(login) LIKE LOWER('js%')
OR LOWER(email) LIKE LOWER('js%')
ORDER BY similarity DESC
结果并不像我希望的那样准确,而且我已经看到野外的自动完成功能按照我希望的方式工作,但不知道它们是如何实现的后端。
谁能指出我正确的方向?
【问题讨论】:
-
你能举一个例子说明结果不是你想要的,你希望它们是什么,为什么?我的第一个猜测是,您希望按最大相似性而不是 4 个组件的相似性总和对结果进行排序,和/或您希望对字段进行加权以匹配用户最有可能搜索的内容.但是如果没有更多细节就很难知道。
-
@JustinCave:不幸的是,由于保密协议,我不能。但是你提出了一些我以前没有想到的有趣的想法。我使用总数的原因是用户可以搜索多个术语(例如“john sm”),并且我将每个以空格分隔的单词视为一个不同的搜索词,对每个词应用所有相同的逻辑。不过,它正在迅速变得笨拙。
-
显然,我不是要求您发布真实数据、真实表结构等。只是您发布的示例数据或多行示例数据的示例,其中排序不是' t 你想要什么。当您搜索您提供的示例“jo”或“js”时,您发布的示例数据似乎工作得相当好,因此很难看出问题是如何回答的。如果您可以说“当我搜索 'jo' 时,我宁愿将 'John Smith' 排序在 'Bob Jones' 之上,因为......”我们可能会提供帮助。否则,我认为这个问题是无法回答的。
-
为什么不围绕匹配制定一些基本规则(例如,4 个字段中的任何一个以输入开头)。所以用户输入“j”,将返回所有行(John,Johnny,Jones,Jane),但对于“jo”,只会得到 3 行(John,Johnny,Jones)。将您的 SQL 简化为仅使用 like 'jo%' 语法,并且在 imo 中更加一致和易于理解。
-
@tbone:我已经在上面的查询中这样做了。
标签: oracle autocomplete