在 MarkLogic 9 中更新 JSON 个数组

Updating JSON arrays in MarkLogic 9

我不知道如何编写一些 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 节点树(和 XML 树,就此而言)是不可变的。

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

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

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

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

希望对您有所帮助,

如果需要更新数据库中的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!