我正在为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文档存储的函数
我需要一种方法来测试给定数组中是否存在值.到目前为止,我想出了类似的东西
select '{1,2,3}'::int[] @> (ARRAY[]::int[] || value_variable::int)
Run Code Online (Sandbox Code Playgroud)
但我一直认为应该有一个更简单的方法,我只是看不到它.
编辑:刚认识到我能做到这一点
select '{1,2,3}'::int[] @> ARRAY[value_variable::int]
Run Code Online (Sandbox Code Playgroud)
这要好得多,我相信这已经足够了,但如果你有其他方法可以做,请分享.
我在文档中找不到这个问题的明确答案.如果列是数组类型,是否会对所有输入的值进行单独索引?
我创建了一个包含一int[]
列的简单表,并在其上放置了一个唯一索引.我注意到我无法添加相同的整数数组,这使我相信索引是数组项的组合,而不是每个项的索引.
INSERT INTO "Test"."Test" VALUES ('{10, 15, 20}');
INSERT INTO "Test"."Test" VALUES ('{10, 20, 30}');
SELECT * FROM "Test"."Test" WHERE 20 = ANY ("Column1");
Run Code Online (Sandbox Code Playgroud)
索引是否有助于此查询?
我正在尝试测试json
PostgreSQL 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专家,所以我不知道我做错了什么.
目前的Postgresql版本已经为JSON内容引入了各种功能,但我担心的是我是否真的应该使用它们 - 我的意思是,还没有"最佳实践"已经确定哪些有效,哪些无效,或者至少我可以'找到它.
我有一个具体的例子 - 我有一个关于对象的表,除其他外,它包含该对象的备用名称列表.所有这些数据也将包含在JSON列中以供检索.例如(跳过所有其他不相关的字段).
create table stuff (id serial primary key, data json);
insert into stuff(data) values('{"AltNames":["Name1","Name2","Name3"]}')
Run Code Online (Sandbox Code Playgroud)
我将需要一些查询形式"列出其中一个altnames为'foobar'的所有对象." 预期的表大小大约为几百万条记录.可以使用Postgres JSON查询,也可以将其编入索引(例如,用于在JSON数组中查找元素的索引).但是,它应该以这种方式完成,还是不建议使用反常的解决方法?
当然,经典的替代方法是为该一对多关系添加一个附加表,其中包含主表的名称和外键; 这种表现很好理解.但是,这有其自身的缺点,因为它意味着该表与JSON之间的数据重复(可能存在完整性风险); 或者在每次请求时动态创建JSON返回数据,这会有自己的性能损失.
以下是我的查询.我试图让它使用索引扫描,但它只会seq扫描.
顺便说一下,这个metric_data
表有1.3亿行.该metrics
表有大约2000行.
metric_data
表格列:
metric_id integer
, t timestamp
, d double precision
, PRIMARY KEY (metric_id, t)
Run Code Online (Sandbox Code Playgroud)
如何让此查询使用我的PRIMARY KEY索引?
SELECT
S.metric,
D.t,
D.d
FROM metric_data D
INNER JOIN metrics S
ON S.id = D.metric_id
WHERE S.NAME = ANY (ARRAY ['cpu', 'mem'])
AND D.t BETWEEN '2012-02-05 00:00:00'::TIMESTAMP
AND '2012-05-05 00:00:00'::TIMESTAMP;
Run Code Online (Sandbox Code Playgroud)
说明:
Hash Join (cost=271.30..3866384.25 rows=294973 width=25)
Hash Cond: (d.metric_id = s.id)
-> Seq Scan on metric_data d (cost=0.00..3753150.28 rows=29336784 width=20)
Filter: ((t >= '2012-02-05 00:00:00'::timestamp without …
Run Code Online (Sandbox Code Playgroud) postgresql indexing query-optimization postgresql-9.1 postgresql-performance
最近升级到使用PostgreSQL 9.3.1来利用JSON功能.在我的表中,我有一个json类型的列,其结构如下:
{
"id": "123",
"name": "foo",
"emails":[
{
"id": "123",
"address": "somethinghere"
},
{
"id": "456",
"address": "soemthing"
}
]
}
Run Code Online (Sandbox Code Playgroud)
这只是用于问题目的的虚拟数据.
是否可以根据ID查询电子邮件数组中的特定项?
差不多:"返回id = 123的电子邮件""?
您将如何搜索存储在json
列中的数组中的元素? (更新:另请参阅jsonb
列的9.4更新答案.)
如果我有这样的JSON文档,则存储在json
名为的列中blob
:
{"name": "Wolf",
"ids": [185603363281305602,185603363289694211]}
Run Code Online (Sandbox Code Playgroud)
我希望能做的是:
SELECT * from "mytable" WHERE 185603363289694211 = ANY("blob"->'ids');
Run Code Online (Sandbox Code Playgroud)
并获取所有匹配的行.但这不起作用,因为"blob"->'ids'
返回JSON值,而不是Postgres数组.
如果可能的话,我还想建立个人ID的索引.
我正在试验jsonb
在Postgres 9.4 中的Postgres 字段中保留以下值:
[{"event_slug":"test_1","start_time":"2014-10-08","end_time":"2014-10-12"},
{"event_slug":"test_2","start_time":"2013-06-24","end_time":"2013-07-02"},
{"event_slug":"test_3","start_time":"2014-03-26","end_time":"2014-03-30"}]
Run Code Online (Sandbox Code Playgroud)
我正在执行以下查询:
SELECT * FROM locations
WHERE EXISTS (
SELECT 1 FROM jsonb_array_elements(events) AS e
WHERE (
e->>'event_slug' = 'test_1' AND
(
e->>'start_time' >= '2014-10-30 14:04:06 -0400' OR
e->>'end_time' >= '2014-10-30 14:04:06 -0400'
)
)
)
Run Code Online (Sandbox Code Playgroud)
如何利用上述查询为该数据创建索引?这对于几百万行来说听起来是否合理?每行包含〜10个事件?
值得注意的是,我似乎仍在进行顺序扫描:
CREATE INDEX events_gin_idx ON some_table USING GIN (events);
Run Code Online (Sandbox Code Playgroud)
我猜是因为我在查询中做的第一件事就是将数据转换为json数组元素.
jsonb
在Postgres 9.4和Rails 的列中使用JSON数组,我可以设置一个范围,返回包含传递给范围方法的数组中的任何元素的所有行- 如下所示:
scope :tagged, ->(tags) {
where(["data->'tags' ?| ARRAY[:tags]", { tags: tags }])
}
Run Code Online (Sandbox Code Playgroud)
我还想根据数组中匹配元素的数量来排序结果.
我很欣赏我可能需要超出ActiveRecord的范围才能做到这一点,所以一个vanilla Postgres SQL的答案也很有帮助,但如果它可以包含在ActiveRecord中,那么它可以是一个可链的范围.
根据要求,这是一个示例表.(实际架构要复杂得多,但这就是我所关心的.)
id | data
----+-----------------------------------
1 | {"tags": ["foo", "bar", "baz"]}
2 | {"tags": ["bish", "bash", "baz"]}
3 |
4 | {"tags": ["foo", "foo", "foo"]}
Run Code Online (Sandbox Code Playgroud)
用例是基于标签查找相关内容.更多匹配标签更相关,因此结果应按匹配数量排序.在Ruby中,我有一个这样的简单方法:
Page.tagged(['foo', 'bish', 'bash', 'baz']).all
Run Code Online (Sandbox Code Playgroud)
哪个应按以下顺序返回页面:2, 1, 4
.
postgresql activerecord ruby-on-rails ruby-on-rails-4 postgresql-9.4
postgresql ×10
json ×5
sql ×4
arrays ×3
indexing ×3
jsonb ×2
lateral ×2
activerecord ×1
mongodb ×1