我有一个存储标题和歌词的应用程序。有些歌曲是西班牙语,包含áccénts。我正在尝试编写一种搜索方法,用户可以在其中输入不带重音的单词。例如,假设标题中包含“papá”一词。如果用户键入“papa”,它仍然应该在标题中找到该单词的歌曲。
这是我到目前为止所拥有的。它处理通配符并搜索3列。
class Song < ApplicationRecord
def self.search(query)
return all unless query.present?
# for case insensitive search
like = Rails.env.production? ? 'ILIKE' : 'LIKE'
# for wildcards
q = ["%#{query}%"] * 3
# columns that I will search through song.number, song.title, song.lyrics
search_phrase = "number #{like} ? OR title #{like} ? OR lyrics #{like} ?"
where([search_phrase] + q)
end
end
答案 0 :(得分:2)
您可以使用整理:
search_phrase = "number #{like} ? OR title COLLATE Latin1_general_CI_AI #{like} ? OR lyrics #{like} ?"
CI代表不区分大小写,AI代表重音不敏感。
答案 1 :(得分:0)
使用postgresql实现此目的的最佳方法是添加unaccent
扩展名:
class AddUnaccentExtension < ActiveRecord::Migration
def change
enable_extension "unaccent"
end
end
然后当您想要查询结果时:
search_phrase = "unaccent(number) #{like} unaccent(?) OR unaccent(title) #{like} unaccent(?) OR unaccent(lyrics) #{like} unaccent(?)"
请记住这只适用于postgresql,我建议你用作开发数据库,以防止发生奇怪的事情
答案 2 :(得分:0)
如果您无法使用COLLATE Latin1_general_CI_AI
或pg
设置,请尝试此操作。重复列,一个重音,一个不重音。积分转到this和this回答。
class Song < ApplicationRecord
before_save :i18n
def self.search(query)
return all unless query.present?
like = Rails.env.production? ? 'ILIKE' : 'LIKE'
q = ["%#{query}%"] * 3
search_phrase = "number #{like} ? OR ai_title #{like} ? OR ai_lyrics #{like} ?"
where([search_phrase] + q)
end
def i18n
self.ai_title = I18n.transliterate title
self.ai_lyrics = I18n.transliterate lyrics
end
end
我的迁移看起来像:
class CreateSongs < ActiveRecord::Migration[5.0]
def change
create_table :songs do |t|
...
t.string :title
t.string :ai_title, index: true
t.text :lyrics
t.text :ai_lyrics, index: true
...
end
end
end
适用于许多数据库设置。我觉得这很有用。