Postgresql 用于多个键/值对的PostgresSQL嵌套jsonb查询

Postgresql 用于多个键/值对的PostgresSQL嵌套jsonb查询,postgresql,postgresql-10,Postgresql,Postgresql 10,从JSONB数据类型开始,我希望有人能帮助我 我有一个表(properties),有两列(id作为主键,data作为jsonb)。 数据结构为: { "ProductType": "ABC", "ProductName": "XYZ", "attributes": [ { "name&

从JSONB数据类型开始,我希望有人能帮助我

我有一个表(properties),有两列(id作为主键,data作为jsonb)。 数据结构为:

    {
        "ProductType": "ABC",
        "ProductName": "XYZ",
        "attributes": [
            {
            "name": "Color",
            "type": "STRING",
            "value": "Silver"
            },
            {
            "name": "Case",
            "type": "STRING",
            "value": "Shells"
            },
            ...
        ]
    }
我希望获取属性具有特定值的所有行,即返回Case='Shells'和/或Color='Red'的所有行

我尝试了以下方法,但无法应用两个条件,如Case='Shells'和Color='Silver'。 当单个属性的名称和值与条件匹配时,我可以获取行,但我不知道如何使其适用于多个属性


编辑1: 我可以使用以下查询获得结果:

WITH properties AS (
    select *
    from (
        values 
        (1, '{"ProductType": "ABC","ProductName": "XYZ","attributes": [{"name": "Color","type": "STRING","value": "Silver"},{"name": "Case","type": "STRING","value": "Shells"}]}'::jsonb), 
        (2, '{"ProductType": "ABC","ProductName": "XYZ","attributes": [{"name": "Color","type": "STRING","value": "Red"},{"name": "Case","type": "STRING","value": "Shells"}]}'::jsonb)
    ) s(id, data)
)
select 
    *
from (
    SELECT 
        id,
        jsonb_object_agg(attr ->> 'name', attr -> 'value') as aggr
    FROM properties m,
       jsonb_array_elements(data -> 'attributes') as attr
    GROUP BY id
    ) a
where aggr ->> 'Color' = 'Red' and aggr ->> 'Case' LIKE 'Sh%'
我可能有数百万条这样的记录,所以我想我现在唯一关心的是这是否有效,如果没有,还有更好的方法吗?

问题是,
jsonb\u array\u elements()
将两个相关值移动到不同的记录中。但是,此调用对于获取值是必需的。因此,您需要在能够读取值之后重新聚合这些值。这将使以相关方式检查它们成为可能

这可以通过使用
jsonb\u object\u agg()
聚合函数来实现。这里的诀窍是,我们创建一个具有属性的对象,如
“name”:“value”
。这样,我们就可以使用
@>
操作符轻松地检查JSON对象中是否存在所有必需的属性


关于“编辑1”

您可以这样做:

SELECT
    *
FROM ( 
    SELECT 
        id,
        jsonb_object_agg(attr ->> 'name', attr -> 'value') as obj
    FROM properties m,
       jsonb_array_elements(data -> 'attributes') as attr
    GROUP BY id
) s
WHERE obj ->> 'Color' = 'Silver'
    AND obj ->> 'Case' LIKE 'Sh%'
  • 如上所述,为所有JSON创建新的JSON结构
  • 之后过滤此结果
  • 或者,您可以根据需要经常在
    HAVING
    子句中使用
    jsonb\u object\u agg()。我想您需要检查哪种方式在您的情况下更有效:

    SELECT 
        id
    FROM properties m,
       jsonb_array_elements(data -> 'attributes') as attr
    GROUP BY id
    HAVING 
       jsonb_object_agg(attr ->> 'name', attr -> 'value') ->> 'Color' = 'Silver'
       AND
       jsonb_object_agg(attr ->> 'name', attr -> 'value') ->> 'Case' LIKE 'Sh%'
    

    是否可以对整数值应用类似“>=”的比较运算符或类似“like”、“EXISTS”的逻辑运算符?我是新来的,但我不会让任何人被绞死,我保证:我不太确定你想要实现什么。请编辑您的问题并显示更新的用例。关于效率有什么想法吗?答案补充道
    SELECT 
        id
    FROM properties m,
       jsonb_array_elements(data -> 'attributes') as attr
    GROUP BY id
    HAVING 
       jsonb_object_agg(attr ->> 'name', attr -> 'value') ->> 'Color' = 'Silver'
       AND
       jsonb_object_agg(attr ->> 'name', attr -> 'value') ->> 'Case' LIKE 'Sh%'