我正在使用PostgreSQL 9.4,其中teams包含一个jsonb名为的列的表json.我正在寻找一个查询,我可以让所有拥有球员的球队3,4以及7他们的球员阵容.
该表包含两行,包含以下json数据:
第一排:
{
"id": 1,
"name": "foobar",
"members": {
"coach": {
"id": 1,
"name": "A dude"
},
"players": [
{
"id": 2,
"name": "B dude"
},
{
"id": 3,
"name": "C dude"
},
{
"id": 4,
"name": "D dude"
},
{
"id": 6,
"name": "F dude"
},
{
"id": 7,
"name": "G dude"
}
]
}
}
Run Code Online (Sandbox Code Playgroud)
第二排:
{
"id": 2,
"name": "bazbar",
"members": …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如上所述?
我有一个表,我想搜索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}]');
Run Code Online (Sandbox Code Playgroud)
如本回答所述,我创建了一个函数,它还允许在数组数据上创建索引(重要).
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;
Run Code Online (Sandbox Code Playgroud)
如果我想找到一个完整的值(例如"Value B1"),这很好用:
SELECT *
FROM data
WHERE '{"Value B1"}'::text[] <@ (json_val_arr(json, 'name'));
Run Code Online (Sandbox Code Playgroud)
现在我的问题:
是否可以使用通配符查找值(例如"Value*")?像以下(天真)方法的东西:
...
WHERE '{"Value%"}'::text[] <@ …Run Code Online (Sandbox Code Playgroud)我正在考虑将PostgreSQL的jsonb列类型用于新的后端项目,该项目主要用作REST-ful JSON API.我相信PostgreSQL jsonb将非常适合这个项目,因为它将为我提供JSON对象而无需在后端进行转换.
但是,我已经读过,jsonb添加密钥时数据类型会变慢,而我的架构需要使用主键和外键引用.
我想知道是否在自己的列中使用主键/外键(以标准的关系数据库方式),然后jsonb为其余数据创建列将是有益的,否则会导致问题(无论是现在还是未来) ?
简而言之,会:
table car(id int, manufacturer_id int, data jsonb)
Run Code Online (Sandbox Code Playgroud)
表现更好或更差:
table car(data jsonb)
Run Code Online (Sandbox Code Playgroud)
特别是在经常查找外键时?
从性能或架构的角度来看,第一个会有缺点吗?
我使用PostgreSQL 9.5和Rails 5.我想查询jsonb下面显示的包含JSON对象数组的列,以返回包含的所有JSON数组元素{"kind":"person"}并执行计数.我使用
的SQL显示在json数据下面.运行查询只返回一个空数组.
这就是我的jsonb数据:
'[
{"kind":"person", "filter_term":"56","selected_attr":"customer"},
{"kind":"email", "filter_term":"marketer","selected_attr":"job_title"}
]'
Run Code Online (Sandbox Code Playgroud)
我想要一个sql查询返回:
data
----------------------------------------------------------------------
'{"kind":"person", "filter_term":"56","selected_attr":"customer"}'
(1 row)
Run Code Online (Sandbox Code Playgroud)
和另一个返回数组的查询,以便我可以在我的应用程序中调用count并在其上循环以创建表单:
data
----------------------------------------------------------------------
'[{"kind":"person", "filter_term":"56","selected_attr":"customer"}]'
(1 row)
Run Code Online (Sandbox Code Playgroud)
我试过这个SQL查询:
"SELECT * FROM \"segments\" WHERE (payload @> '[{\"kind\":\"person\"}]')"
Run Code Online (Sandbox Code Playgroud)
我也试过这个查询:
"SELECT payload FROM segments WHERE payload @> '[{\"kind\":\"person\"}]'::jsonb;"
Run Code Online (Sandbox Code Playgroud)
这是第三个查询:
"SELECT * FROM segments s WHERE s.payload->'\"#{a}\"' @> '[{\"kind\":\"person\"}]';"
Run Code Online (Sandbox Code Playgroud)
该模型:
class Segment < ApplicationRecord
store_accessor :payload,:kind, :filter_term, :selected_model_name, :selected_attr, :limit, :selected_operator …Run Code Online (Sandbox Code Playgroud) 背景:我们使用 PaperTrail 来保存我们不断变化的模型的历史。现在我想查询属于某个客户的项目。PaperTrail 可选择存储object_changes,我需要查询此字段以了解何时使用此 ID 创建或更改为此 ID。
我的表看起来像这样简化:
item_type | object_changes
----------|----------------------------------------------------------
"Item" | {"customer_id": [null, 5], "other": [null, "change"]}
"Item" | {"customer_id": [4, 5], "other": ["unrelated", "change"]}
"Item" | {"customer_id": [5, 6], "other": ["asht", "asht"]}
Run Code Online (Sandbox Code Playgroud)
如何查询从 ID 5 更改为或更改为 ID 5 的元素(所以上面的所有行)?我试过:
SELECT * FROM versions WHERE object_changes->'customer_id' ? 5;
Run Code Online (Sandbox Code Playgroud)
这让我:
Run Code Online (Sandbox Code Playgroud)ERROR: operator does not exist: jsonb ? integer LINE 1: ...T * FROM versions WHERE object_changes->'customer_id' ? 5; ^ HINT: No operator matches the given name …
postgresql ruby-on-rails paper-trail-gem jsonb postgresql-9.6
我在决定使用哪种方法时遇到了一些麻烦.
我有几个实体"类型",让我们称它们为A,B和C,它们共享一定数量的属性(大约10-15).我创建了一个名为ENTITIES的表,以及每个常用属性的列.
A,B,C也有一些(大部分)唯一属性(所有布尔值,可以是10到30左右).我不确定在对表建模时遵循的最佳方法是什么:
我倾向于使用3,但我想知道是否有更好的解决方案.
我试图在Postgres数据库中查询某个值.我有一个groups在users表中命名的字段,可以用以下任何一种方式表示:
1.
groups: {"data"=>[{"serie"=>5, "year"=>3, "specialization"=>"Matematica", "management_id"=>1, "group_number"=>2}, {"serie"=>5, "year"=>3, "specialization"=>"Matematica", "management_id"=>1, "group_number"=>2}]}
Run Code Online (Sandbox Code Playgroud)
2.
groups: [{"serie"=>5, "year"=>3, "specialization"=>"Matematica", "management_id"=>1, "group_number"=>2}, {"serie"=>5, "year"=>3, "specialization"=>"Matematica", "management_id"=>1, "group_number"=>2}]
Run Code Online (Sandbox Code Playgroud)
我对这两种表述都很好.但是,我似乎无法找到如何让所有在系列5中的用户让我们说.我尝试了多个查询:
@users = User.where("groups ->> 'data' @> ?", {serie: 5})
@users = User.where("groups -> 'data' @> '?'", {serie: 5})
@users = User.where("groups ->> 'data' ->> 'serie' = ?", 5)
Run Code Online (Sandbox Code Playgroud)
还有许多其他尝试,有些比其他尝试更愚蠢(见上文).我该怎么办?
我已经能够确定:
select groups -> 'data' ->> 'serie' from users;
ERROR: cannot extract field from a non-object.
Run Code Online (Sandbox Code Playgroud)
但是以下查询有效:
select json_array_elements(groups -> 'data') …Run Code Online (Sandbox Code Playgroud) 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, …
我有一个来自 json 对象的数组:[1, 9, 12]
由于它使用方括号表示法,因为它是直接从 json 对象获取的,所以我无法将其转换为,::integer[]当我尝试使用时,array_agg(jsonb_array_elements(simpleintarray))我收到一条错误消息,说我需要按 id 进行分组,但由于数组不是对象(键/值) )对,但只是简单的整数,我不知道如何以相当有效的方式实现这一点。
从 json 返回上述简单 int 数组的查询是:
SELECT node.*, elem->'permissions' AS group_node_permissions
FROM node
LEFT OUTER JOIN
jsonb_array_elements(my_user_group.node_permissions) elem
ON elem->>'id' = node.id::text
ORDER BY node.id
Run Code Online (Sandbox Code Playgroud)
elem->'permissions'理想情况下应该以 Postgres 数组的形式返回{},以便我稍后可以在其上使用该ANY(intarray)函数。
我想避免做多余的低效解决方法,例如用大括号替换方括号,然后转换elem->'permissions'为->>整数数组,将其转换为字符串,尽管这可能会起作用。
在伪代码中,我真正需要的是能够得到相同的结果:
SELECT node.*, elem->'permissions'**::integer[]** AS group_node_permissions,
...但是当然由于json 数组与 PostgreSQL 数组格式之间的[]差异{},这会导致错误。
这是我当前的(非常丑陋的解决方案,但有效):
SELECT node.*, replace(replace(elem->>'permissions', '[', '{'),']','}')::integer[] AS group_node_permissions
Run Code Online (Sandbox Code Playgroud)
它将原始的 (jsonb) 转换为(integer[])[1, 9, …
postgresql ×10
sql ×6
json ×5
jsonb ×5
arrays ×2
foreign-keys ×1
hstore ×1
indexing ×1
types ×1