You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MarkLogic中xdmp.nodeInsertChild插入JSON数组报错问题咨询

插入JSON数组到MarkLogic文档时触发xdmp.nodeInsertChild异常的排查

问题描述

我写了一段脚手架代码,用来在数据库现有JSON对象中插入或更新节点——逻辑是如果XPath能找到对应字段就更新,找不到就插入到父节点下。这段代码处理普通字段没问题,但插入数组时调用xdmp.nodeInsertChild会抛出异常,更新数组却能正常执行。想知道这是Bug还是操作错误?

现有JSON文档示例

{"saying": {"quote": "I'd rather regret the things I've done than regret the things I haven't done", "person": "Lucille Ball", "born": "Jamestown, New York, USA", "dob": "1911-08-05", "category": ["fun", "inspirational"], "likes": 3, "foo": "bar", "babson": [1, 2, 3]}}

执行代码

将代码中的babson改为babo会触发异常,更新babson则正常执行:

'use strict';
declareUpdate();
let node = new NodeBuilder();
let nb = node.addNode({"likes": 3,"dob":"1911-08-05","foo":"bar","babson": [1,2,3]}).toNode();

let props = []
for(const [key, value] of Object.entries(nb)) {
  props.push(key)
}
let doc = cts.doc("/sayings/lb_regret.json")

//console.log(`======${xdmp.random()}======`)

for(let prop of props) {
  let propPath = `/saying/${prop}`
  let propSeq = doc.xpath(propPath)
  if(propSeq.toArray().length !== 0) {
    xdmp.nodeReplace(propSeq,nb[prop])
  } else {
    let cnb = new NodeBuilder()
    let child = {}
    child[prop] = nb[prop];
    let childNode = cnb.addNode(child)
    xdmp.nodeInsertChild(doc.xpath('/saying'), childNode.toNode().xpath(`/${prop}`))
  }
}

抛出的错误信息

[javascript] XDMP-ARGTYPE: xdmp.nodeInsertChild(Sequence(xdmp.unpath("fn:doc('/sayings/lb_regret.json')/saying")), Sequence(NumberNode(1), NumberNode(2), NumberNode(3))) -- arg2 is not of type Node

Stack Trace
In undefined on line 24
In xdmp.nodeInsertChild(Sequence(xdmp.unpath("fn:doc('/sayings/lb_regret.json')/saying")), Sequence(NumberNode(1), NumberNode(2), NumberNode(3)))

问题原因

这不是Bug,是操作有误。核心问题出在插入分支的xpath(/${prop})调用上:

  • 当prop对应的值是数组时,childNode.toNode().xpath(/${prop})返回的是数组元素的节点序列(比如NumberNode(1), NumberNode(2), NumberNode(3)),而非包含数组的JSON属性节点。
  • xdmp.nodeInsertChild要求第二个参数是合法的节点或节点序列,但数组元素序列不符合JSON属性节点的类型要求,因此触发XDMP-ARGTYPE类型错误。

修复方案

插入时直接传入完整的属性节点,而非提取数组元素。修改插入分支的代码:

} else {
  let cnb = new NodeBuilder()
  let child = {}
  child[prop] = nb[prop];
  // 直接获取包含数组的属性节点
  let childNode = cnb.addNode(child).toNode().firstChild;
  xdmp.nodeInsertChild(doc.xpath('/saying'), childNode)
}

为什么更新分支正常?

更新时使用的nb[prop]本身就是数组对应的节点序列,xdmp.nodeReplace可以直接替换已存在的数组属性节点,因为替换序列与原节点类型匹配。

内容的提问来源于stack exchange,提问作者garyvidal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 22:57:38