Rails中PostgreSQL jsonb字段多语言翻译计数查询错误
解决PostgreSQL jsonb字段统计有效翻译条目的问题
看起来你遇到的问题是PostgreSQL对空字符串和NULL的处理和你预期的不一样,咱们一步步理清楚:
首先看你的示例数据,fr对应的值是"Jaune"(非空有效内容),但执行Translation.where("values->>'fr' IS NOT NULL").count却返回0,这大概率是因为你的查询条件没命中真正的有效条目——毕竟PostgreSQL里空字符串和NULL是完全不同的概念。
问题根源
PostgreSQL的->>操作符会把jsonb字段里的键值转换为文本类型:
- 如果键存在但值是空字符串
"",values->>'fr'返回空字符串(不是NULL) - 如果键根本不存在,
values->>'fr'才会返回NULL
所以你原来的IS NOT NULL条件,会把所有fr键存在的条目都算进去(包括空字符串的无效条目),但如果你的实际数据里有效条目是fr有非空内容的,这个条件就没精准命中。
正确的查询方式
要统计fr语言有非空有效翻译的条目,你需要判断值既不是NULL也不是空字符串,最简洁的写法是:
# 统计fr字段有非空内容的有效条目 Translation.where("values->>'fr' <> ''").count
这个语句会自动排除两种无效情况:
fr键不存在(此时values->>'fr'是NULL,NULL和空字符串比较结果为NULL,不会被包含进查询结果)fr键存在但值是空字符串""
如果你的数据里还有JSON类型的NULL(即"fr": null),可以加上额外的判断来覆盖这种情况:
Translation.where("values->>'fr' IS NOT NULL AND values->>'fr' <> ''").count
额外技巧:一次性统计所有语言的有效条目
如果你不想逐个语言写查询,想一次性拿到所有语言的有效翻译数量,可以用PostgreSQL的jsonb函数实现:
# 批量统计每种语言的有效翻译数 Translation.select("key AS language, count(*)") .from("translations, jsonb_each_text(translations.values)") .where("value <> ''") .group("key")
这样就能直接得到所有语言的有效条目统计结果,效率比逐个查询高很多。
内容的提问来源于stack exchange,提问作者Arb
相关产品推荐
相关产品推荐

