嵌入式json对象的唯一索引

时间:2014-09-21 12:30:24

标签: json postgresql indexing unique-index postgresql-9.4

我正在测试Postgresql 9.4 beta2。我想知道是否可以在嵌入式json对象上创建唯一索引?

我创建了一个表名products

CREATE TABLE products (oid serial primary key, data jsonb)

现在,我尝试将json对象插入数据列。

{
    "id": "12345",
    "bags": [
        {
            "sku": "abc123",
            "price": 0,
        },
        {
            "sku": "abc123",
            "price": 0,
        }
    ]
}

但是,我希望sku行李袋是唯一的。这意味着json无法插入到产品表中,因为在这种情况下sku不是唯一的。

我尝试创建一个如下所示的唯一索引,但它失败了。

CREATE UNIQUE INDEX product_sku_index ON products( (data->'bags'->'sku') )

有什么建议吗?

1 个答案:

答案 0 :(得分:4)

由于多种原因,您在表达式上创建UNIQUE INDEX的尝试肯定会失败。

<击> CREATE UNIQUE INDEX product_sku_index ON products( (data->'bags'->'sku') )

第一个也是最微不足道的...... <击> data->'bags'->'sku'
引用任何。您可以使用

引用数组的 first 元素
data->'bags'->0->>'sku'

或更短:

data#>>'{bags,0,sku}'

但该表达式只返回数组的第一个值 你的定义:&#34;我希望袋子的sku是独一无二的&#34; ..目前还不清楚。您希望sku的值是唯一的吗?在一个JSON对象中或data列中的所有json对象中?或者您是否希望将数组限制为具有sku

的单个元素

无论哪种方式,这些目标都不能用简单的UNIQUE索引来实现。

可能的解决方案

如果您希望sku data->'bags'中的所有json数组中都是唯一的,则有一种方法。将数组unnest并将所有单独的sku值写入具有唯一(或PK)约束的简单辅助表中的单独行:

CREATE TABLE prod_sku(sku text PRIMARY KEY);  -- PK enforces uniqueness

此表可能有助于其他目的 这是一个完整的代码示例,用于与普通Postgres数组非常相似的问题:

只适应不需要的技术。而不是:

DELETE FROM hostname h
USING  unnest(OLD.hostnames) d(x)
WHERE  h.hostname = d.x;

...

INSERT INTO hostname(hostname)
SELECT h
FROM   unnest(NEW.hostnames) h;

使用:

DELETE FROM prod_sku p
USING  jsonb_array_elements(NEW.data->'bags') d(x)
WHERE  p.sku = d.x->>'sku';

...

INSERT INTO prod_sku(sku)
SELECT b->>'sku'
FROM   jsonb_array_elements(NEW.data->'bags') b

的详细信息