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
相关产品推荐
相关产品推荐

