如何将pg_search_scope与Mobility结合实现多语言翻译属性搜索
实现方案
这个需求完全可以实现,你当前搜索返回空的核心原因是:pg_search默认会从categories主表查询name字段,但你使用Mobility的key_value后端时,所有翻译内容存储在独立的string_translations关联表中,主表不存在name字段,自然匹配不到结果。
具体修改步骤
1. 修改模型中的pg_search配置
调整pg_search_scope为动态参数形式,自动关联翻译表并按当前locale过滤匹配:
class Category < ApplicationRecord extend Mobility translates :name, type: :string include PgSearch::Model pg_search_scope :search, ->(query, locale = I18n.locale) { { associated_against: { string_translations: :value }, using: { trigram: { threshold: 0.3, word_similarity: true } }, # 过滤仅匹配当前语言、name属性的翻译记录 conditions: -> { where(string_translations: { locale: locale, key: 'name' }) } } } end
2. 调整控制器代码,统一预加载翻译避免N+1查询
def index @categories = params[:query].present? ? Category.search(params[:query]).includes(:string_translations) : Category.all.includes(:string_translations) end
可选优化方案(性能更佳)
如果你的业务场景支持调整Mobility后端,可将key_value后端替换为column后端,直接在categories表新增name_en、name_de字段存储翻译,此时搜索配置会更简单,查询性能也更高:
修改后模型配置
class Category < ApplicationRecord extend Mobility translates :name, type: :string, backend: :column include PgSearch::Model pg_search_scope :search, ->(query, locale = I18n.locale) { { against: :"name_#{locale}", using: { trigram: { threshold: 0.3, word_similarity: true } } } } end
这种方式无需关联翻译表,直接查询主表字段即可,适合数据量较大的场景。
内容的提问来源于stack exchange,提问作者axcr
相关产品推荐
相关产品推荐

