sql - 如何在postgres中过滤json的任何键的值

标签 sql json postgresql jsonb

我有一个表 users,其中有一个名为 datajsonb 字段。我必须检索所有在该 data 列中具有匹配给定字符串的 value 的用户。例如:

user1 = data: {"property_a": "a1", "property_b": "b1"}
user2 = data: {"property_a": "a2", "property_b": "b2"}

我想检索具有与 'b2' 匹配的值 data 的任何用户,在本例中为 'user2'

知道如何以优雅的方式做到这一点吗?我可以从所有用户的 data 中检索所有键并手动创建查询,但这既不快速也不优雅。

此外,我必须检索匹配的键和值,但首先要做的是。

最佳答案

没有简单的方法。 Per documentation:

GIN indexes can be used to efficiently search for keys or key/value pairs occurring within a large number of jsonb documents (datums)

大胆强调我的。没有所有 的索引。 (它们可能具有不兼容的数据类型!)如果您不知道所有键的名称,则必须检查每一行中的所有 JSON 值。

如果像您演示的那样只有两个键(或者只有几个众所周知的键),它仍然很容易:

SELECT *
FROM   users
WHERE  data->>'property_a' = 'b2' OR
       data->>'property_b' = 'b2';

可以用一个简单的 expression index 来支持:

CREATE INDEX foo_idx ON users ((data->>'property_a'), (data->>'property_b'))

或者使用 GIN 索引:

SELECT *
FROM   users
WHERE  data @> '{"property_a": "b2"}' OR
       data @> '{"property_b": "b2"}'

CREATE INDEX bar_idx ON users USING gin (data jsonb_path_ops);

如果您不知道所有键名,事情就会变得更加复杂......

你可以使用 jsonb_each() or jsonb_each_text()将所有值取消嵌套到一个集合中,然后使用 ANY 构造进行检查:

SELECT *
FROM   users
WHERE  jsonb '"b2"' = ANY (SELECT (jsonb_each(data)).value);

或者

...
WHERE  'b2' = ANY (SELECT (jsonb_each_text(data)).value);

db<> fiddle here

但是最后一个没有索引支持。您可以改为将所有值提取到数组中并在其上创建表达式索引,然后在查询中使用数组运算符匹配该表达式...

相关:

关于sql - 如何在postgres中过滤json的任何键的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29609161/

相关文章:

mysql - 如何添加在同一个表中选择的临时列?

javascript - 如何将Json数组从ajax发送到spring Controller ?

Python 3 将 json 值读取为元组

mysql - 如果 image_id 计数大于 5,则删除?

sql - 如何用空格替换返回的所有零

postgresql - st_intersect() 在 postgresql 中不起作用

postgresql - 使用 slick 的 3.0.0 流式结果和 Postgresql 的正确方法是什么?

sql - 从一个表中获取一组 ID,并使用它们在不同的表中生成一行

android - 卸载使用 PhoneGap 构建的应用程序时,android 会删除应用程序 SQL 数据库吗?

ios - JSON 和 Xcode 6 UITableView