如何使用Mongoid/MongoDB跨所有语言查询本地化字段?
嘿,这个问题我之前在项目里也遇到过,其实关键点在于Mongoid本地化字段的存储结构——当你给name加上localize: true后,实际存在数据库里的是name_translations这个哈希字段,包含所有语言的翻译值。我们直接针对这个字段做查询就能实现跨语言匹配,下面给你几种实用的实现方式:
1. 精确匹配任意语言的名称
如果要找任意语言里名称完全匹配目标字符串的文档,直接查询name_translations的所有值即可:
# 匹配任意语言中名称为"Computer Software"的文档 Foo.where('name_translations.values': 'Computer Software') # 匹配任意语言中名称是多个目标值之一的文档 Foo.where('name_translations.values': { '$in': ['Computer Software', 'Ingénierie logicielle'] })
2. 模糊匹配(包含关键词)
如果需要做模糊查询(比如找名称里包含某个关键词的文档),可以结合MongoDB的$regex操作符:
# 不区分大小写的模糊匹配,找任意语言名称含"Software"的文档 Foo.where('name_translations.values': { '$regex': /Software/i }) # 也可以用字符串形式的正则,适合动态传入查询词的场景 query = "Software" Foo.where('name_translations.values': { '$regex': Regexp.escape(query), '$options': 'i' })
这里用Regexp.escape是为了避免查询词里的特殊正则字符(比如.、*)干扰匹配结果。
3. 封装成模型方法(方便复用)
如果你的项目经常需要做这种跨语言查询,建议在Foo模型里封装一个类方法,让调用更简洁:
class Foo field :name, localize: true # 跨语言模糊查询名称 def self.by_any_language_name(query) escaped_query = Regexp.escape(query) where('name_translations.values': { '$regex': escaped_query, '$options': 'i' }) end # 跨语言精确查询名称 def self.by_exact_any_language_name(name) where('name_translations.values': name) end end # 使用示例 Foo.by_any_language_name('Software') Foo.by_exact_any_language_name('Ingénierie logicielle')
为什么默认的find_by不行?
默认的Foo.find_by(name: 'xxx')只会匹配当前I18n.locale对应的翻译值,因为Mongoid会自动把name字段的查询映射到name_translations[I18n.current.locale],所以只能查到当前语言的匹配项。而直接查询name_translations.values就能遍历所有语言的翻译内容,实现跨语言匹配。
内容的提问来源于stack exchange,提问作者Cyril Duchon-Doris
相关产品推荐
相关产品推荐

