【问题标题】:Remove jsonb array element by value按值删除 jsonb 数组元素
【发布时间】:2017-03-10 04:41:21
【问题描述】:

我确实想出了如何从数组中删除单个记录的值,但是如何为其中的许多记录执行此操作。问题在于我如何使用子查询。因为它必须只返回单个元素。也许我的方法是错误的。

给定输入:'{attributes:['is_new', 'is_old']}' 预期结果 '{attributes: ['is_old']}' #remove 'is_new' from jsonb array 真实例子: # 货号 |特性 # --------+-------------------------------- # nu3_1 | { + # | "名称": "silly_hodgkin", + # | “类型”:“食物”,+ # | “属性”:[+ # | "is_gluten_free", + # | "is_lactose_free", + # | "是新的" + # | ] + # | } #删除单个数组元素的查询: 选择 c.sku, jsonb_agg(el) FROM 目录 c JOIN (select sku, jsonb_array_elements_text(properties->'attributes') as el from catalog) c2 ON c.sku=c2.sku where el 'is_new' 按 c.sku 分组; #更新删除单个记录中单个数组元素的查询 更新目录 SET properties=jsonb_set(properties, '{attributes}', ( 选择 jsonb_agg(el) 来自 目录 c JOIN (select sku, jsonb_array_elements_text(properties->'attributes') as el from catalog) c2 ON c.sku=c2.sku WHERE el 'is_new' AND c.sku='nu3_1' 按 c.sku 分组 ) ) 哪里 sku='nu3_1';

问题又来了。多条数据库记录如何按值删除jsonb数组元素?

【问题讨论】:

    标签: arrays json postgresql jsonb


    【解决方案1】:

    使用jsonb_set() and the delete operator -:

    update catalog
    set properties = 
        jsonb_set(properties, '{attributes}', (properties->'attributes') - 'is_new');
    

    db<>fiddle.测试它

    【讨论】:

    • 我确实尝试了'-'运算符,然后在这里提出问题,但它没有用。使它起作用的是括号(properties->'attributes')。没有它们,它就行不通。我不明白。有什么区别?我现在明白了 '->' 和 '-' 都是运算符。看起来,'-' 具有更高的优先级,它试图将它用于两个字符串,这是行不通的。谢谢@klin。
    • 可以在哪里做吗?假设您在一个数组中有一个具有 ID 的对象,并且 ID = 1?
    • @NickPocock - 是的,您可以像在任何其他 UPDATE 语句中一样添加 where 子句,请参阅 this example.
    • 这样的事情怎么样? stackoverflow.com/questions/42299061/… 苦苦挣扎!
    • 嗨,@klin,如果我有一个内容为 [123, 345, 789] 的字段 parents,我可以使用 jsonb_set 删除一个元素,例如 123,或者是否有任何其他解决方案?
    【解决方案2】:

    所以,我相信您正在寻找的 QRY 是:

    with q as (
      select distinct sku, jsonb_set(properties,'{attributes}',jsonb_agg(el) over (partition by sku),false) new_properties
      from (
        select 
          sku, jsonb_array_elements_text(properties->'attributes') as el, properties
        from catalog
      ) p
      where el != 'is_new'
    )
    update catalog set properties = q.new_properties from q where catalog.sku = q.sku
    ;
    

    请注意,我假设您的 sku 至少是 UK

    【讨论】:

    • 我只是重写了问题 qry,这样它就可以工作了。我自己肯定更喜欢 - 操作员
    【解决方案3】:

    您的解决方案有效 + 您向我指出了一些新的东西,例如窗口函数,并为我提供了替代解决方案的想法:

    WITH q as (
      SELECT c.sku as sku,  jsonb_set(properties, '{attributes}', jsonb_agg(el)) as new_properties
        FROM catalog c JOIN (select sku, jsonb_array_elements_text(properties->'attributes') as el from catalog) c2 ON c.sku=c2.sku where el != 'is_new'
        GROUP BY c.sku
    )
    UPDATE catalog SET properties=q.new_properties FROM q WHERE catalog.sku=q.sku;
    

    【讨论】:

      【解决方案4】:

      根据documentation:

      json_build_object (VARIADIC "any") → json

      jsonb_build_object (VARIADIC "any") → jsonb

      根据可变参数列表构建 JSON 对象。按照惯例, 参数列表由交替的键和值组成。钥匙 参数被强制转换为文本;值参数按 to_json 或 to_jsonb。

      json_build_object('foo', 1, 2, row(3,'bar')) → {"foo" : 1, "2" : {"f1":3,"f2":"bar"}}

      update catalog
      set properties = properties - 'attributes' || jsonb_build_object('attributes','[is_gluten_free,is_lactose_free,is_new]')
      where properties ? 'attributes' 
      returning *;
      

      现在您可以替换键,也可以替换值。只需确保 attributes 为顶级键即可。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-07-12
        • 1970-01-01
        • 2022-05-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多