1

我正在实现一个自动完成功能,允许用户输入部分文本,然后将其与表中的 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”,那么由于它的值loginemail列值,只有第一条记录会匹配。等等。我还想返回按相似度排序的结果,其中第一个结果是“最接近的匹配”,依此类推(标准自动完成行为)。

我目前一直在尝试使用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

1 回答 1

0

搜索总是很有趣。你已经开始了一个非常好的基本方法。我通常做的是创建一个通过触发器加载的辅助表。触发器从您的用户表中加载主键,第二列是“搜索”列。在您的示例中,每一行将产生 4 行。确保以大写形式存储结果,以便您可以索引列,Oracle 将使用该索引,因为您坚持使用类似的语法。它需要一个额外的表,但是可以通过触发器维护该表。

    create table searcher
    (
    user_id  number, --FK back to users
    search_column  varchar2(50) -- or whatever size column is appropriate
    );

    select u.first_name, u.last_name, u.login. u.email,
utl_match.jaro_winkler_similarity(search_column, 'js')
    from users u
    join
    searcher s
    on (u.user_id = s.user_id)
    where s.search_column like upper('js%')
    order by 5;
于 2012-05-18T02:03:45.370 回答