You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Rails查询translations表中jsonb字段的未翻译记录?

嘿,我来帮你解决这个PostgreSQL jsonb字段的查询问题!你要找translations表里values字段中存在未翻译(空字符串)的记录,之前的写法没用到PostgreSQL对jsonb的原生支持,所以没生效。下面分几种常见场景给你靠谱的解决方案:

解决方案

1. 查找任意语言翻译为空的记录

这是最常见的需求——只要某个语言的翻译是空字符串,就返回这条记录。我们可以用PostgreSQL的jsonb_each_text函数把jsonb字段拆成键值对行,再结合EXISTS子查询过滤:

Translation.where(<<~SQL)
  EXISTS (
    SELECT 1
    FROM jsonb_each_text(values) AS t(lang, text)
    WHERE t.text = ''
  )
SQL

这个查询的逻辑是:遍历每条Translation的values字段,把它拆成「语言-文本」的行数据,只要其中有任意一行文本是空字符串,就把这条Translation记录选出来。

2. 查找特定语言翻译为空的记录

如果你只关心某个特定语言(比如英文en)的空翻译,写法会更简单:

直接写SQL字符串

Translation.where("values ->> 'en' = ''")

这里的->>是PostgreSQL的jsonb操作符,用来提取指定键的文本值,然后判断是否等于空字符串。

更安全的Arel写法(适合语言是变量的场景)

如果语言是动态传入的,用Arel可以避免SQL注入问题:

target_lang = 'en' # 可以是任意变量
Translation.where(Translation.arel_table[:values].get_text(target_lang).eq(''))

3. 查找所有语言都未翻译的记录

如果要找那些values里所有语言的翻译都是空字符串的记录,可以用反向的EXISTS查询:

Translation.where(<<~SQL)
  NOT EXISTS (
    SELECT 1
    FROM jsonb_each_text(values) AS t(lang, text)
    WHERE t.text != ''
  )
SQL

意思是:如果这条记录的values里找不到任何非空的翻译文本,就把它选出来。

为什么你之前的写法不对?
  • 你尝试的Translation.where(values.values=""):ActiveRecord会把values.values当成SQL的一部分,但PostgreSQL根本不认识这个语法,自然会报错。
  • 你写的循环遍历Translation.all.values.each:这种方法会把所有Translation记录加载到内存里再遍历,数据量小的时候还行,但数据量大的时候会严重影响性能,而且代码逻辑也没必要这么复杂,直接用数据库查询高效得多。

内容的提问来源于stack exchange,提问作者Arb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:44:02