我有一个表格,其中包含我想要搜索的 JSON 数组数据。
CREATE TABLE data (id SERIAL, json JSON);
INSERT INTO data (id, json)
VALUES (1, '[{"name": "Value A", "value": 10}]');
INSERT INTO data (id, json)
VALUES (2, '[{"name": "Value B1", "value": 5}, {"name": "Value B2", "value": 15}]');
如 this answer 中所述,我创建了一个函数,它还允许在数组数据上创建索引(重要)。
CREATE OR REPLACE FUNCTION json_val_arr(_j json, _key text)
RETURNS text[] AS
$$
SELECT array_agg(elem->>_key)
FROM json_array_elements(_j) AS x(elem)
$$
LANGUAGE sql IMMUTABLE;
如果我想找到一个完整的值(例如“值 B1”),这很有效:
SELECT *
FROM data
WHERE '{"Value B1"}'::text[] <@ (json_val_arr(json, 'name'));
现在我的问题:
是否可以使用通配符(例如“Value*”)查找值?类似于以下(天真的)方法:
... WHERE '{"Value%"}'::text[] <@ (json_val_arr(json, 'name'));
是否可以使用比较运算符(例如 >= 10)查找数值?同样,一种幼稚且明显错误的方法:
... WHERE '{10}'::int[] >= (json_val_arr(json, 'value'));
我尝试创建一个返回
int[]
的新函数,但没有成功。
我创建了一个 SQL Fiddle来说明我的问题。
或者使用不同的方法会更好,例如以下工作查询:
SELECT *
FROM data,
json_array_elements(json) jsondata
WHERE jsondata ->> 'name' LIKE 'Value%';
和
...
WHERE cast(jsondata ->> 'value' as integer) <= 10;
但是,对于这些查询,我无法创建查询实际获取的任何索引。
此外,我最终想在 Postgresql 9.4 中使用 JSONB 实现所有这些,但我认为对于上述问题,这应该不是问题。
非常感谢!
最佳答案
我知道已经有一段时间了,但我只是在做类似的事情(使用通配符查询 json 数据类型)并想分享我的发现。
首先,这是朝着正确方向迈出的重要一步: http://schinckel.net/2014/05/25/querying-json-in-postgres/
要点是,将 json 元素分解为其他内容(记录集)的方法是可行的方法。它允许您使用普通的 postgres 内容查询 json 元素。
以我为例:
#Table:test
ID | jsonb_column
1 | {"name": "", "value": "reserved", "expires_in": 13732}
2 | {"name": "poop", "value": "{\"ns\":[\"Whaaat.\"]}", "expires_in": 4554}
3 | {"name": "dog", "value": "{\"ns\":[\"woof.\"]}", "expires_in": 4554}
示例查询
select * from test jsonb_to_recordset(x) where jsonb_column->>'name' like '%o%';
# => Returns
# 2 | {"name": "poop", "value": "{\"ns\":[\"Whaaat.\"]}", "expires_in": 4554}
然后回答您关于 jsonb 的问题:看起来 jsonb 大多数时候是更好的路由。它有更多的方法和更快的读取(但更慢的写入)时间。
来源:
- http://www.postgresql.org/docs/9.4/static/functions-json.html
- http://www.postgresql.org/docs/9.4/static/datatype-json.html
狩猎愉快!
关于sql - Postgresql:通过通配符和带索引的比较运算符在 JSON 数组中查找值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25059853/