我正在为PostgreSQL 9.2中的新JSON函数寻找一些文档和/或示例.
具体来说,给定一系列JSON记录:
[
{name: "Toby", occupation: "Software Engineer"},
{name: "Zaphod", occupation: "Galactic President"}
]
Run Code Online (Sandbox Code Playgroud)
如何编写SQL以按名称查找记录?
在vanilla SQL中:
SELECT * from json_data WHERE "name" = "Toby"
Run Code Online (Sandbox Code Playgroud)
官方开发手册非常稀少:
我已经汇总了详细介绍PostgreSQL 9.2目前可能实现的内容.使用一些自定义函数,可以执行以下操作:
SELECT id, json_string(data,'name') FROM things
WHERE json_string(data,'name') LIKE 'G%';
Run Code Online (Sandbox Code Playgroud)
我现在已将我的JSON函数移动到他们自己的项目中:
PostSQL - 一组用于将PostgreSQL和PL/v8转换为完全令人敬畏的JSON文档存储的函数
我正在尝试测试jsonPostgreSQL 9.3中的类型.
我在一个json名为data的表中调用了一列reports.JSON看起来像这样:
{
"objects": [
{"src":"foo.png"},
{"src":"bar.png"}
],
"background":"background.png"
}
Run Code Online (Sandbox Code Playgroud)
我想查询表中所有与'objects'数组中'src'值匹配的报告.例如,是否可以在数据库中查询匹配的所有报告'src' = 'foo.png'?我成功写了一个可以匹配的查询"background":
SELECT data AS data FROM reports where data->>'background' = 'background.png'
Run Code Online (Sandbox Code Playgroud)
但由于"objects"有一系列的价值观,我似乎无法写出有用的东西.是否可以在数据库中查询匹配的所有报告'src' = 'foo.png'?我查看了这些来源,但仍然无法得到它:
我也尝试过这样的事情,但无济于事:
SELECT json_array_elements(data->'objects') AS data from reports
WHERE data->>'src' = 'foo.png';
Run Code Online (Sandbox Code Playgroud)
我不是SQL专家,所以我不知道我做错了什么.
我有一个看起来像这样的表:
CREATE TABLE tracks (id SERIAL, artists JSON);
INSERT INTO tracks (id, artists)
VALUES (1, '[{"name": "blink-182"}]');
INSERT INTO tracks (id, artists)
VALUES (2, '[{"name": "The Dirty Heads"}, {"name": "Louis Richards"}]');
Run Code Online (Sandbox Code Playgroud)
还有其他几个与此问题无关的列.将它们存储为JSON是有原因的.
我要做的是查找具有特定艺术家姓名(完全匹配)的曲目.
我正在使用此查询:
SELECT * FROM tracks
WHERE 'ARTIST NAME' IN
(SELECT value->>'name' FROM json_array_elements(artists))
Run Code Online (Sandbox Code Playgroud)
例如
SELECT * FROM tracks
WHERE 'The Dirty Heads' IN
(SELECT value->>'name' FROM json_array_elements(artists))
Run Code Online (Sandbox Code Playgroud)
但是,这会进行全表扫描,并且速度不是很快.我尝试使用函数创建GIN索引names_as_array(artists)并使用'ARTIST NAME' = ANY names_as_array(artists),但是不使用索引并且查询实际上明显更慢.
当我有一个具有分隔值的列时,我可以使用该unnest()函数:
myTable
id | elements
---+------------
1 |ab,cd,efg,hi
2 |jk,lm,no,pq
3 |rstuv,wxyz
select id, unnest(string_to_array(elements, ',')) AS elem
from myTable
id | elem
---+-----
1 | ab
1 | cd
1 | efg
1 | hi
2 | jk
...
Run Code Online (Sandbox Code Playgroud)
我如何包含元素编号?即:
id | elem | nr
---+------+---
1 | ab | 1
1 | cd | 2
1 | efg | 3
1 | hi | 4
2 | jk | 1
...
Run Code Online (Sandbox Code Playgroud)
我想要源字符串中每个元素的原始位置.我试着窗口函数(row_number(), …
sql arrays postgresql window-functions set-returning-functions
我在匹配表中有以下数据:
5;{"Id":1,"Teams":[{"Name":"TeamA","Players":[{"Name":"AAA"},{"Name":"BBB"}]},{"Name":"TeamB","Players":[{"Name":"CCC"},{"Name":"DDD"}]}],"TeamRank":[1,2]}
6;{"Id":2,"Teams":[{"Name":"TeamA","Players":[{"Name":"CCC"},{"Name":"BBB"}]},{"Name":"TeamB","Players":[{"Name":"AAA"},{"Name":"DDD"}]}],"TeamRank":[1,2]}
Run Code Online (Sandbox Code Playgroud)
我想按名称选择表格中每个最后一个不同的团队.即我想要一个将返回的查询:
6;{"Name":"TeamA","Players":[{"Name":"CCC"},{"Name":"BBB"}
6;{"Name":"TeamB","Players":[{"Name":"AAA"},{"Name":"DDD"}
Run Code Online (Sandbox Code Playgroud)
所以每个团队从上次那个团队出现在表中.
我一直在使用以下(从这里):
WITH t AS (SELECT id, json_array_elements(match->'Teams') AS team FROM matches)
SELECT MAX(id) AS max_id, team FROM t GROUP BY team->'Name';
Run Code Online (Sandbox Code Playgroud)
但这回归:
Run Code Online (Sandbox Code Playgroud)ERROR: could not identify an equality operator for type json SQL state: 42883 Character: 1680
我知道Postgres 没有JSON的相等性.我只需要团队名称(字符串)的相等性,该团队中的队员不需要进行比较.
任何人都可以建议另一种方法吗?
以供参考:
SELECT id, json_array_elements(match->'Teams') AS team FROM matches
Run Code Online (Sandbox Code Playgroud)
收益:
5;"{"Name":"TeamA","Players":[{"Name":"AAA"},{"Name":"BBB"}]}"
5;"{"Name":"TeamB","Players":[{"Name":"CCC"},{"Name":"DDD"}]}"
6;"{"Name":"TeamA","Players":[{"Name":"CCC"},{"Name":"BBB"}]}"
6;"{"Name":"TeamB","Players":[{"Name":"AAA"},{"Name":"DDD"}]}"
Run Code Online (Sandbox Code Playgroud)
编辑:我转向text并关注这个问题,我用DISTINCT ON而不是GROUP BY.这是我的完整查询:
WITH t AS (SELECT id, …Run Code Online (Sandbox Code Playgroud) 在PostgreSQL 9.3中,我存储了一些相当复杂的JSON对象,其中数组嵌套在数组中.此片段不是真实数据,但说明了相同的概念:
{
"customerId" : "12345",
"orders" : [{
"orderId" : "54321",
"lineItems" : [{
"productId" : "abc",
"qty" : 3
}, {
"productId" : "def",
"qty" : 1
}]
}
}
Run Code Online (Sandbox Code Playgroud)
我希望SQL查询能够对lineItem对象进行操作...不仅在这个单一的JSON结构中,而且在该表列中的所有JSON对象中.例如,一个SQL查询返回所有不同productId的,以及它们的总销售额qty.为了防止这样的查询花了一整天,我可能想要索引lineItem或其子字段.
使用这个StackOverflow问题,我想出了如何编写一个有效的查询:
SELECT
line_item->>'productId' AS product_id,
SUM(CAST(line_item->>'qty' AS INTEGER)) AS qty_sold
FROM
my_table,
json_array_elements(my_table.my_json_column->'orders') AS order,
json_array_elements(order->'lineItems') AS line_item
GROUP BY product_id;
Run Code Online (Sandbox Code Playgroud)
但是,最初的StackOverflow问题处理的是仅嵌套一层而不是两层的数据.我扩展了相同的概念(即条款中的"横向连接" FROM),通过添加额外的横向连接来深入潜水.但是,我不确定这是否是最佳方法,因此我的问题的第一部分是:查询JSON对象中任意数量级别的 JSON数据的最佳方法是什么?
对于第二部分,在此类嵌套数据上创建索引,此StackOverflow问题再次处理仅嵌套一层深度的数据.然而,我只是完全迷失了,我的头脑游泳试图想想如何将这个应用到更深层次的水平.任何人都可以提供一个明确的方法来索引至少两个级别的数据,lineItems如上所述?
I have a table say types, which had a JSON column, say location that looks like this:
{ "attribute":[
{
"type": "state",
"value": "CA"
},
{
"type": "distance",
"value": "200.00"
} ...
]
}
Run Code Online (Sandbox Code Playgroud)
Each row in the table has the data, and all have the "type": "state" in it. I want to just extract the value of "type": "state" from every row in the table, and put it in a new column. I checked out several questions on SO, …
是否可以使用ILIKE(icontains)运算符搜索字典列表中的一个键值?我的json字段看起来像这样:
object = MyModel()
object.json_data = [
{
"type": 1,
"results": [
{
"score": 1,
"comment": "Some text comment 1",
},
{
"score": 2,
"comment": "Some text comment 2",
},
{
"score": 3,
"comment": "Some text comment 3",
}
]
},
{
"type": 2,
"results": [
{
"score": 4,
"comment": "Some text comment 4",
},
{
"score": 5,
"comment": "Some text comment 5",
},
{
"score": 6,
"comment": "Some text comment 6",
}
]
}
]
object.save()
Run Code Online (Sandbox Code Playgroud)
现在,如何编写查询以在"注释"键中搜索?
MyModel.objects.filter(json_data__??__results__??__comment__icontains="text comment") …Run Code Online (Sandbox Code Playgroud) 假设我有下parents表:
create table parents (
id integer not null constraint parents_pkey primary key,
name text not null,
children jsonb not null
);
Run Code Online (Sandbox Code Playgroud)
其中children有一个如下结构的json数组:
[
{
"name": "child1",
"age": 10
},
{
"name": "child2",
"age": 12
}
]
Run Code Online (Sandbox Code Playgroud)
例如,我需要找到所有有 10 岁到 12 岁孩子的父母。
我创建以下查询:
select distinct
p.*
from
parents p, jsonb_array_elements(p.children) c
where
(c->>'age')::int between 10 and 12;
Run Code Online (Sandbox Code Playgroud)
当表parents很大时(例如 1M 条记录),它工作得很好,但速度很慢。我尝试在children字段上使用“杜松子酒”索引,但这没有帮助。
那么有没有办法加快此类查询的速度呢?或者也许还有另一种解决方案可以对嵌套 json 数组中的字段进行查询/索引?
查询计划:
Unique (cost=1793091.18..1803091.18 …Run Code Online (Sandbox Code Playgroud)