【问题标题】:Updating JSON arrays in MarkLogic 9在 MarkLogic 9 中更新 JSON 数组
【发布时间】:2017-09-13 12:03:21
【问题描述】:

我无法弄清楚如何编写一点 XQuery。我在 MarkLogic 中有一个 JSON 结构,如下所示:

{
    "id": "pres003A10",
    "title": "A Course About Something",
    "description": "This course teaches people about some things they may not know.",
    "author": "A.N. Author",
    "updated": "2007-01-19",
    "decks": [
      {
        "id":"really-basic-stuff",
        "exclude": ["slide3", "slide12"]
      },
      {
        "id":"cleverer-stuff",
        "exclude": []
      }
    ]           
  }

exclude 数组包含幻灯片中幻灯片的标识符(演示文稿由一张或多张幻灯片组成)。我正在尝试编写一段代码,它将在该排除列表中查找幻灯片 ID,如果存在则将其删除,如果不存在则添加它(切换)。

我可以使用以下方法获取数组节点本身:

let $exclude := doc('/presentations/presentation.json')/object-node()/decks[id = 'markup-intro']/array-node('exclude')

但我无法终生了解如何更新该数组以删除或添加项目。目的是调用一个类似的函数:

local:toggle-slide($presentation) as object-node()
{
   (: xdmp:node-update(...) goes here :)
};

那么,如何更新该数组?

【问题讨论】:

    标签: json xquery marklogic marklogic-9


    【解决方案1】:

    在内存中 JSON 节点树(以及 XML 树,就此而言)是不可变的。

    修改一棵树的方法是构造一棵新树,复制没有变化的节点,并根据变化创建父节点和祖先节点。

    也就是说,有一种更简单的方法可以修改 JSON。如果你在根节点上调用xdmp:from-json(),你会得到一个可变的内存映射/数组结构。

    然后,您可以使用地图上的map:get() 和数组上的 [ITEM_NUMBER] 导航到数组,并删除或插入适当的 json:array 对象的项目。

    完成后,调用xdmp:to-json() 将根映射转回节点。

    希望对您有所帮助,

    【讨论】:

    • 我实际上不需要在内存中修改它 - 更改被写回数据库。我根本看不到如何更改(对于“更改”一词的某些值)数组节点。不过,你给了我一些东西可以尝试。谢谢。
    【解决方案2】:

    如果需要更新数据库中的json,可以使用xdmp:node-replace。使用 node-replace 的问题是,您必须使用命名节点来提供它。为此,您需要将数组节点包装在对象节点中,然后动态抓取对象节点内的数组节点。这是一个工作示例:

    xquery version "1.0-ml";
    
    (: insert test data :)
    xdmp:document-insert("/presentations/presentation.json", xdmp:unquote('{
        "id": "pres003A10",
        "title": "A Course About Something",
        "description": "This course teaches people about some things they may not know.",
        "author": "A.N. Author",
        "updated": "2007-01-19",
        "decks": [
          {
            "id":"markup-intro",
            "exclude": ["slide3", "slide12"]
          },
          {
            "id":"cleverer-stuff",
            "exclude": []
          }
        ]           
      }'
    ))
    ;
    
    (: node-replace array-node :)
    let $exclude := doc('/presentations/presentation.json')/object-node()/decks[id = 'markup-intro']/array-node('exclude')
    return xdmp:node-replace($exclude, object-node{
      "exclude": array-node{ "other", "slides" }
    }/node())
    ;
    
    (: view if changed :)
    doc('/presentations/presentation.json')
    

    注意:考虑查看 MarkLogic 的 Server-side JavaScript (SJS) 支持。以这种方式更新 JSON 可能看起来更自然,特别是如果您需要一次性进行多项更改。

    HTH!

    【讨论】:

    • 这对我有用。谢谢。一个问题 - 最终的 doc(/presentations/presentations.json`) 实际上返回了未更改的文档,尽管我可以通过查询控制台看到更改的文档。这会是交易问题吗?
    • 是的,很有可能。我的代码示例在更新和读取部分之间使用分号,这种技巧只适用于主模块..
    猜你喜欢
    • 1970-01-01
    • 2016-10-24
    • 1970-01-01
    • 1970-01-01
    • 2018-05-18
    • 1970-01-01
    • 2017-07-21
    • 1970-01-01
    • 2022-01-04
    相关资源
    最近更新 更多