Heroku上的Rails 3.1中的Postgres重音不敏感LIKE搜索

use*_*849 16 postgresql ruby-on-rails unaccent rails-postgresql

如何在Rails中修改搜索查询的where/like条件:

find(:all, :conditions => ["lower(name) LIKE ?", "%#{search.downcase}%"])

无论重音如何,结果都是匹配的?(例如métro= metro).因为我使用的是utf8,所以我不能使用"to_ascii".生产正在Heroku上运行.

Erw*_*ter 28

穷人的解决方案

如果您能够创建一个功能,则可以使用此功能.我从这里开始编译列表并随着时间的推移添加到列表中.它非常完整.您甚至可能想要删除一些字符:

CREATE OR REPLACE FUNCTION lower_unaccent(text)
  RETURNS text AS
$func$
SELECT lower(translate($1
     , '¹²³áàâãäå???ÀÁÂÃÄÅ???Æ??ç©??Ç?Ðèéê?ë?????ÈÊË??????€???ìíîïì???ÌÍÎÏ?Ì???????ñ??Ñòóôõö???øÒÓÔÕÖ???ØŒ?®?š??ߊ??ùúûü????ÙÚÛÜ????ýÿÝŸž??Ž??'
     , '123aaaaaaaaaaaaaaaaaaacccccccddeeeeeeeeeeeeeeeeeeeeggiiiiiiiiiiiiiiiiiillnnnnnnooooooooooooooooooorrrsssssssuuuuuuuuuuuuuuuuyyyyzzzzzz'
     ));
$func$ LANGUAGE sql IMMUTABLE;
Run Code Online (Sandbox Code Playgroud)

您的查询应该像这样工作:

find(:all, :conditions => ["lower_unaccent(name) LIKE ?", "%#{search.downcase}%"])
Run Code Online (Sandbox Code Playgroud)

对于左锚定搜索,您可以使用函数索引获得非常快速的结果:

CREATE INDEX tbl_name_lower_unaccent_idx
  ON fest (lower_unaccent(name) text_pattern_ops);
Run Code Online (Sandbox Code Playgroud)

对于以下查询:

SELECT * FROM tbl WHERE (lower_unaccent(name)) ~~ 'bob%'
Run Code Online (Sandbox Code Playgroud)

适当的解决方案

PostgreSQL 9.1+中,具有必要的权限,您可以:

CREATE EXTENSION unaccent;
Run Code Online (Sandbox Code Playgroud)

它提供了一个功能unaccent(),做你需要的(除了lower(),如果需要,只需另外使用).阅读有关此扩展手册.
也适用于PostgreSQL 9.0,CREATE EXTENSION语法是9.1中的新功能.

有关unaccent和索引的更多信息:

  • (3年后:) Heroku包括`unaccent`:https://devcenter.heroku.com/articles/heroku-postgres-extensions-postgis-full-text-search你可以通过运行`echo'show extwlist.extensions来验证| heroku pg:psql` (2认同)
  • 它工作得很好。我通过迁移将它插入到我的 rails 应用程序中。这是一个很好的例子,说明如何做到这一点:http://stackoverflow.com/questions/16611226/how-to-install-postgres-extensions-at-database-creation (2认同)

Edi*_*ado 14

对于像我这样在添加unaccentPostgreSQL扩展程序并使其与Rails应用程序一起工作时遇到问题的人,以下是您需要创建的迁移:

class AddUnaccentExtension < ActiveRecord::Migration
  def up
    execute "create extension unaccent"
  end

  def down
    execute "drop extension unaccent"
  end
end
Run Code Online (Sandbox Code Playgroud)

当然,在rake db:migrate您能够unaccent在查询中使用该功能之后:unaccent(column) similar to ...unaccent(lower(column)) ...

  • 通过这样做验证扩展是否尚不存在将防止迁移崩溃: ``` def upexecute "create extension if not exit unaccent" end ``` (2认同)