使用MarkLogic:有没有办法获得括号表示法中的“.find”行为?

问题描述 投票:0回答:1

我正在尝试考虑一种将字符串存储在变量中的方法,以便将该字符串用作 JSON 属性的“路径”,以便我可以更新该属性。

我的想法是,我有一个基础文档,有人想修改它,以查看更改某些属性后该文档的外观。

所以,我的想法是我可以存储一个包含如下所示对象的数组:

                    {
                        "LineItem": {
                            "Path": "/LevelA1/LevelB1/PropertyA",
                            "Value": 12345
                        }
                    

我什至可以“路径”到数组中的特定对象,如下所示:

                    {
                        "LineItem": {
                            "Path": "/LevelA1/LevelB2/.[PropertyC3=\"ValueD3\"]/PropertyD4",
                            "Value": 12345
                        }
                    }

但是,我不知道如何获取 MarkLogic 中的

.xpath
功能以允许我更新该路径上的值。

因此,我试图从我的文档中创建一个对象并更新该对象(因为我真正要做的就是在服务中返回更新后的对象,我并没有真正将其写入数据库)。

我的想法是使用点表示法字符串,并使用如下函数迭代在点处分隔它的字符串:

function setDepth(obj, path, value) {
    var tags = path.split("."), len = tags.length - 1;
    for (var i = 0; i < len; i++) {
        obj = obj[tags[i]];
    }
    obj[tags[len]] = value;
}

但是,这只在没有数组时才有效,我必须

find
要更新适当的对象。

我无法弄清楚是否有括号符号可以为您提供“where”功能(又名点符号中的“.find”)。

我可以这样做:

updatedDoc.LevelA1.LevelB2.find(x => x["PropertyC3"] === "ValueD3").PropertyD4
和这个:
copiedObject["LevelA1"]["LevelB2"].find(x => x["PropertyC3"] === "ValueD3")["PropertyD4"]

但我只是不知道是否有括号符号可以让我获得

.find
功能。因为这破坏了
setDepth
功能:
'LevelA1.LevelB2.find(x => x["PropertyC3"] === "ValueD3").PropertyD4'
当传递为
path
时。

所以,如果有人知道:

  1. 实际上如何使用“.xpath”在 MarkLogic 中的 javascript (sjs) 中更新内存中对象 或
  2. 如何使用方括号表示法实现
    find
    功能 或
  3. 是否有更好的方法来完成同样的事情(循环遍历“某物”数组,处理有关大型分层 JSON 对象中特定属性的信息,该对象包含具有这些特定属性的数组)

我将不胜感激...

javascript json marklogic
1个回答
0
投票

MarkLogic 使用的一种方法是利用

xdmp.nodeReplace()
。是的,这确实“写入”了一个临时文档,并且有一个事务。然而,了解 MarkLogic 的内部结构后,所讨论的结构位于内存中。这种方法的好处是,
doc.nodeReplace()
的路径与
node.xpath()

的路径完全相同

我们让 Mark Logic 承担繁重的工作并隔离需要更改的内容。

方法:

  • 写入临时文档(在内存架中)

  • 更改临时文档(使用 xPath)

  • 阅读更改的文档

  • 删除文档

     var doc = {
       foo:123,
       bar:{
         baz:[
       1,2,{buz:12}
       ]
     }
     }
    
     const tempUri = "temp-" + sem.uuidString()
     const path  = "/bar/baz[3]/buz"
    
     //insert
     xdmp.invokeFunction(function(){
       declareUpdate();
       xdmp.documentInsert(tempUri, doc);
     })
    
     //update via xPath
     xdmp.invokeFunction(function(){
       declareUpdate();
       var n = new NodeBuilder();
       newBuz = n.addNumber(19).toNode();
       xdmp.nodeReplace(cts.doc(tempUri).xpath(path), newBuz);
     })
    
     //read again
     var newDoc = xdmp.invokeFunction(function(){
       return cts.doc(tempUri)
     }).toObject()
    
     xdmp.invokeFunction(function(){
       declareUpdate();
       return xdmp.documentDelete(tempUri)
     }).toObject()
    
    
     newDoc
    

原文:(buz=12)

    {
      "foo": 123, 
      "bar": {
        "baz": [
          1, 
          2, 
          {"buz": 12}
        ]
      }
    }

结果:(嗡嗡声是19)

    {
      "foo": 123, 
      "bar": {
        "baz": [
          1, 
          2, 
          {"buz": 19}
        ]
      }
    }

你能在记忆中完成这一切吗? 是的 - 使用递归并使用 node.path() 测试每个节点。然而,每个节点更大的文档和递归/测试可能会消耗更多的时间和资源。上面的好处是 MarkLogic 通用索引的一部分是所有值的路径都已经被索引了。

© www.soinside.com 2019 - 2024. All rights reserved.