0

我的用户模型有:

用户(id、fname、lname)

我需要一个查询来按名称搜索用户。我一直在使用:

@users = User.find( :all,
                      :select => 'users.*',
                      :conditions => ["fname || ' ' || lname LIKE ?", '%'+"James Bond"+'%']
                    )

如果您搜索 James,则返回用户 (James Bond),但如果您搜索“Bond”,则不会返回任何内容。如何更新此查询以通过 fname、lname 或 fname 和 lname 返回用户?

谢谢

4

1 回答 1

1

我不知道您如何在 RoR 中指定它,但在 PostgreSQL 级别,听起来您可能想要使用三元组搜索。如果您使用的是 PostgreSQL 版本 9.1 或更高版本,您可以将其与“K 最近邻”(KNN)搜索结合起来,直接返回 K 最佳匹配。这通常比其他名称的“模糊”搜索技术快几个数量级。

要安装 trigram 支持,如果您的机器上有 contrib 模块,请键入:

CREATE EXTENSION pg_trgm;

假设两个名称字段都是NOT NULL(只是为了避免用COALESCE谓词混淆答案),可以使用以下方法创建索引:

CREATE INDEX users_name ON users USING gist
  ((fname || ' ' || lname) gist_trgm_ops);

这是有趣的部分,您可以在几毫秒内从数百万条记录中找到近似匹配:

SELECT *
  FROM users
  ORDER BY (fname || ' ' || lname) <-> 'James Bond'
  LIMIT 10;

<->算子是“距离”算子。当该ORDER BY子句用于针对用 定义的索引的子句gist_trgm_ops 并且您使用 aLIMIT时,将从索引中以“最佳匹配”序列返回行。

于 2012-08-23T02:14:05.703 回答