json 使用MarkLogic:有没有一种方法可以在括号表示法中获得“.find”行为?

gc0ot86w  于 2023-10-21  发布在  其他
关注(0)|答案(1)|浏览(136)

我正在想办法将字符串存储在变量中,以便将该字符串用作JSON属性的“路径”,以便更新该属性。
这个想法是,我有一个基本文档,有人想修改,看看文档的外观与某些属性的变化。
所以,我的想法是,我可以存储一个数组,其中包含这样的对象:

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

我甚至可以“path”到数组中的特定对象,像这样:

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

但是,我不知道如何在MarkLogic中获得.xpath功能,以允许我更新该路径上的值。
所以,我试图从我的文档中创建一个Object并更新Object(因为我真正要做的就是在服务中返回更新后的Object,我并没有真正将其写入数据库)。
我的想法是使用一个点符号字符串,并在字符串上用一个像这样的函数在点处分隔它:

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)中的内存对象,或者
1.如何使用括号表示法实现find功能,
1.是否有更好的方法来完成同样的事情(循环遍历一个“某物”数组,该数组处理一个大型分层JSON对象中特定属性的信息,该对象包括具有这些特定属性的数组)
我会很感激...
好吧,为了提供一个例子,这里是“文档”:

{
    "envelope": {
        "headers": {
            "sources": [
                {
                    "name": "MadeUp"
                }
            ]
        },
        "triples": [],
        "instance": {
            "Root": {
                "PropertyA1": {
                    "PropertyB1": 1,
                    "PropertyB2": 2
                },
                "PropertyA2": [
                    {
                        "PropertyB3": 3,
                        "PropertyB4": 4,
                        "PropertyB5": 5,
                        "PropertyB6": "ValueB1",
                        "PropertyA3": [
                            {
                                "PropertyC1": {
                                    "PropertyD1": 6,
                                    "PropertyD2": "ValueD1"
                                }
                            }
                        ]
                    }
                ]
            }
        }
    }
}

下面是等价的“路径”-点表示法和xpath:

{
    "LineItems": [
        {
            "LineItem": {
                "Path": "envelope.instance.Root.PropertyA1.PropertyB1",
                "Xpath": "/envelope/instance/Root/PropertyA1/PropertyB1"
            }
        },
        {
            "LineItem": {
                "Path": "envelope.instance.Root.PropertyA1.PropertyB2",
                "Xpath": "/envelope/instance/Root/PropertyA1/PropertyB2"
            }
        },
        {
            "LineItem": {
                "Path": "envelope.instance.Root.PropertyA2.find(x => x.PropertyB6 === 'ValueB1').PropertyB3",
                "Xpath": "/envelope/instance/Root/PropertyA2/.[PropertyB6='ValueB1']/PropertyB3"
            }
        },
        {
            "LineItem": {
                "Path": "envelope.instance.Root.PropertyA2.find(x => x.PropertyB6 === 'ValueB1').PropertyB4",
                "Xpath": "/envelope/instance/Root/PropertyA2/.[PropertyB6='ValueB1']/PropertyB4"
            }
        },
        {
            "LineItem": {
                "Path": "envelope.instance.Root.PropertyA2.find(x => x.PropertyB6 === 'ValueB1').PropertyB5",
                "Xpath": "/envelope/instance/Root/PropertyA2/.[PropertyB6='ValueB1']/PropertyB5"
            }
        },
        {
            "LineItem": {
                "Path": "envelope.instance.Root.PropertyA2.find(x => x.PropertyB6 === 'ValueB1').PropertyA3.find(x => x.PropertyC1.PropertyD2 === 'ValueD1').PropertyC1.PropertyD1",
                "Xpath": "/envelope/instance/Root/PropertyA2/.[PropertyB6='ValueB1']/PropertyA3/PropertyC1[PropertyD2='ValueD1']/PropertyD1"
            }
        }
    ]
}

那么,有没有一种方法来处理JavaScript中的点符号“string”,或者有没有一个括号符号来做等效的事情(这实际上是https://youmightnotneed.com/lodash#set正在做的事情)?

wwtsj6pe

wwtsj6pe1#

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()

 // cleanup
 xdmp.invokeFunction(function(){
   declareUpdate();
   return xdmp.documentDelete(tempUri)
 })

 newDoc

Original:(buz=12)

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

结果:(buz为19)

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

上面的好处是MarkLogic的通用索引的一部分是所有值的路径已经被索引。
你能在记忆中做到这一切吗?是-使用递归和测试每个节点和它的路径。每个节点上更大的文档和递归/测试可能会消耗更多的时间和资源。

相关问题