【问题标题】:How to do regexp for add new json element in Postgres如何在 Postgres 中添加新的 json 元素的正则表达式
【发布时间】:2015-04-15 02:22:21
【问题描述】:

我所拥有的和我所知道的:

  • json 数组,例如 {"home":["1","2","5"], "work":["15","16","19"]}
  • 新的整数元素(例如“11”)
  • 新元素“家”或“工作”的位置(例如“家”)

我需要什么:

  • 将此元素添加到 json 数组末尾的正确位置
  • 用正则表达式来做
  • 在 postgreSQL 中使用 regexp_replace 执行此操作
  • 结果必须是这样的:{"home":["1","2","5","11"], "work":["15","16","19"]}

我的尝试:

SELECT regexp_replace('{"home":["1","2","5"], "work":["15","16","19"]}', '(.*)("home":\[)(("[0-9]*",)*("[0-9]*")*)(\])(.*)', '\1\2\3,"11"\6\7', 'g');

我不知道的: - 如果地方是“家”:[],我必须把“11”不带“,”!怎么样?

【问题讨论】:

    标签: regex json postgresql-9.3 regexp-replace


    【解决方案1】:

    我不是 postgresql 专家,但你或许可以试试这个技巧:

    SELECT regexp_replace('{"home":["1","2","5"], "work":["15","16","19"]}' || ',"11"', '("home":\[)(?:(].*)(.{4}$)|([^]]+)(.*)(.{5}$))|.{5}$', '\1\3\4\2\6\5', 'g');
    

    想法是将原始字符串与之前的,"11" 连接起来。当数组为空时,组 3 仅捕获 "11",但当数组不为空时,组 6 捕获 ,"11"

    .{5}$ 将匹配字符串末尾的,"11",由于所有捕获组均为空,它将被替换字符串删除。

    显然,量词必须适应您要添加的字符串的长度。因此,如果您想添加13240,则模式将是:

    ("home":\[)(?:(].*)(.{7}$)|([^]]+)(.*)(.{8}$))|.{8}$
    

    你可以看一个例子here

    注意:无需显式量词也可以这样做:

    ("home":\[)(?:(].*)("[^"]*"$)|([^]]+)(.*)(,"[^"]*"$))|,"[^"]*"$
    

    【讨论】:

    • 感谢您的回复!我试过你的代码,结果在“home”部分没有“11”:{“home”:[“1”,“2”,“5”],“work”:[“15”,“16”, 19"]}。
    • 看起来很不错!但是 postgres 像以前一样返回原始字符串 || ',"11"'
    • 为什么regex101.com/r/aP6zY7/1 上的示例像魅力一样工作,而 postgres 不是:(
    • @noonehos:可能无法在前瞻中使用捕获组,所以我构建了一个没有它们的版本。
    【解决方案2】:

    不要使用正则表达式来处理 JSON。这只是个坏主意。就像 HTML 一样,JSON 不是常规语言。 JSON 应该被解析以进行处理。

    我在纯 SQL 中工作了很长时间,但它变得很丑。然后我安装了PL/v8,我花了大约 10 分钟。安装它(安装会因平台而异),然后运行:

    CREATE EXTENSION plv8;
    

    然后很容易。我刚刚创建了一个函数:

    CREATE OR REPLACE FUNCTION add_to_keyed_list(obj JSON, obj_key TEXT, new_value JSON)
      RETURNS JSON
      LANGUAGE plv8
      AS $$
        obj[obj_key].push(new_value);
        return JSON.stringify(obj);
      $$
    ;
    

    是的,那是您数据库中的 JavaScript 代码。

    运行查询:

    SELECT add_to_keyed_list('{"home":["1","2","5"], "work":["15","16","19"]}'::JSON, 'home', to_json('11'::TEXT));
    

    得到你想要的东西:

    {"home":["1","2","5","11"],"work":["15","16","19"]}
    

    我认为可以公平地说 PG 目前并没有很好的工具来修改 JSON,但 regex 也肯定不是一个很好的工具。 PL/v8绝对是 JSON 处理的合法选择。

    【讨论】:

    • 今天试试。我可以将它用于 1000 行更新或 100 000 行吗?它的工作速度有多慢?什么是更快的 JS 函数或 REGEXP?谢谢!
    • @noonehos 您必须进行基准测试。在您实际测试之前,无法确定。我可以说正则表达式将更难编写,更难理解,并且更容易破坏(无论是当您尝试更改它时,还是在您没有考虑的边缘情况下)。只要您的用例可以接受性能,那些(属于“正确性”和“可维护性”类别)对我来说胜过性能。性能始终是最后要考虑的事情。我希望它们具有相似的性能,但这只是猜测。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-13
    • 2016-12-08
    • 2011-08-22
    • 2016-05-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多