首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >MarkLogic中用于多个集合中文档的复杂Xquery

MarkLogic中用于多个集合中文档的复杂Xquery
EN

Stack Overflow用户
提问于 2019-09-10 12:47:33
回答 3查看 237关注 0票数 1

我们在MarkLogic中拥有庞大的数据集,文档分布在多个集合中。我们需要通过搜索分布在这些集合中的文档来开发报告。

样本数据集:

代码语言:javascript
代码运行次数:0
运行
复制
    Collection1 - Inventory [Contains 5 million Inventory documents]

    URI: /inventory/inv1
        <xml>
            <INVENTORY>
                <ItemName>10</ItemName>
                <InventoryQuantity>100</InventoryQuantity>
                .
                .
            </INVENTORY>
        </xml>


    Collection2 - Item[Contains 1 million Item documents]

    URI: /item/item1
        <xml>
            <Item>
                <ItemName>10</ItemName>
                <ItemWmos>
                    <UnitPrice>895</UnitPrice>
                    .
                    .
                <ItemWmos>
                .
                .
            </Item>
        </xml>


          For each Inventory in the Inventory collection
            Step 1 : Get "ItemName", its "InventoryQuantity" and for the same "ItemName" find "UnitPrice" from Item document in Item collection.
            Step 2 : CurrentInventoryValue = InventoryQuantity * UnitPrice
            Step 3 : TotalInventoryValue = TotalInventoryValue + CurrentInventoryValue;
         Repeat;

使用下面的XQuery,我已经达到了上述报告要求。然而,执行和显示超时异常需要大量时间。我无法在这里利用路径范围索引,因为我必须将"ItemName“和它的"InventoryQuantity”放在一起,并在具有相同项目名称的不同集合文档中搜索单价。

XQuery:

代码语言:javascript
代码运行次数:0
运行
复制
    sum(for $doc in cts:search(doc(), cts:and-query((cts:collection-query("Inventory"))))
        [(fn:string-length(//INVENTORY/ItemName/text()) > 0) and (fn:string-length(//INVENTORY/InventoryQuantity/text()) > 0)]
        let $itemName := $doc//INVENTORY/ItemName/text()
        let $inventoryQuantity := $doc//INVENTORY/InventoryQuantity/text()
    return (
        for $doc in cts:search(doc(), cts:and-query((cts:collection-query("Item"))))[//Item/ItemName/text()=$itemName 
        and (fn:string-length(//ItemWmos/UnitPrice/text()) > 0)]
        return ($inventoryQuantity * $doc//ItemWmos/UnitPrice/text())
    ))

如何有效地在MarkLogic中实现这样复杂的查询需求?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-09-10 15:20:20

波段援助方法:

通过将XPath表达式重写为绝对表达式并将它们转换为cts查询逻辑,您可能可以获得更好的性能。但是,即使它解决了眼前的问题,它也不会扩大到更远的范围(因为您可以迭代的文档数量没有限制):

(注意:我还没有测试过这段代码,所以可能存在语法错误)

代码语言:javascript
代码运行次数:0
运行
复制
sum(for $doc in cts:search(doc(), cts:and-query((cts:collection-query("Inventory"))), "unfiltered")
        let $itemName := $doc/xml/INVENTORY/ItemName/string()
        let $inventoryQuantity := $doc/xml/INVENTORY/InventoryQuantity/string()
    where
      fn:string-length($itemName) gt 0 and fn:string-length($inventoryQuantity) gt 0
    return (
        for $doc in cts:search(doc(), cts:and-query((cts:collection-query("Item")), cts:elementValueQuery("ItemName", $itemName)), "unfiltered")
        return (xs:integer($inventoryQuantity) * xs:integer($doc/xml/Item/ItemWmos/UnitPrice/string()))
    ))

可扩展方法#1:

我要做的第一件事是将您在MarkLogic中拥有的/inventory/ data转换为以下格式,并将其还原为所摄取的数据:

代码语言:javascript
代码运行次数:0
运行
复制
<envelope>
  <headers xmlns="http://yoursite.com/item/headers"> <!-- Note the unique namespace -->
     <ItemName>10</ItemName>
     <InventoryQuantity>100</InventoryQuantity>
     <UnitPrice>85</UnitPrice>
     <ItemPrice>8500</ItemPrice>
  </headers>
  <attachments>
    <INVENTORY>
      <ItemName>10</ItemName>
      <InventoryQuantity>100</InventoryQuantity>
      .
      .
    </INVENTORY>
    <Item>
      <ItemName>10</ItemName>
      <ItemWmos>
        <UnitPrice>895</UnitPrice>
        .
        .
      </ItemWmos>
      .
      .
    </Item>
 </attachments>
</envelope>

现在,要运行报告,只需在<ItemPrice>上放置一个<ItemPrice>并运行cts:总和-合计

如果您使用DataHub框架,您可以更简单地管理用于提取不相交数据并协调它的过程。

可扩展方法#2:

您可以保持数据的原样,但也可以将TDE视图放在其之上,这将对数据进行索引,并允许您使用Optic来运行性能连接和从中聚合。这有一些背景开销,这使得方法1在苹果与苹果之间的比较中表现得更好,但是快速运行更广泛的各种查询的灵活性,而不必改变吞食,可能会使它对您来说是值得的。

票数 2
EN

Stack Overflow用户

发布于 2019-10-15 05:49:30

请在URI上使用xdmp:目录进行迭代。

代码语言:javascript
代码运行次数:0
运行
复制
let $var1:=<xml>
    <INVENTORY>
        <ItemName>10</ItemName>
        <InventoryQuantity>100</InventoryQuantity>
    </INVENTORY>
    <INVENTORY>
        <ItemName>10</ItemName>
        <InventoryQuantity>101</InventoryQuantity>
    </INVENTORY>
    <INVENTORY>
        <ItemName>12</ItemName>
        <InventoryQuantity>102</InventoryQuantity>
    </INVENTORY>
</xml>


let $var2:=
<xml>
    <Item>
        <ItemName>10</ItemName>
        <ItemWmos>
            <UnitPrice>895</UnitPrice>
        </ItemWmos>
    </Item>
    <Item>
        <ItemName>11</ItemName>
        <ItemWmos>
            <UnitPrice>896</UnitPrice>
        </ItemWmos>
    </Item>
    <Item>
        <ItemName>12</ItemName>
        <ItemWmos>
            <UnitPrice>897</UnitPrice>
        </ItemWmos>
    </Item>
</xml>

let $mergeInvertory:= <merge>{for $in in $var2//Item/ItemName[. eq $var1//INVENTORY/ItemName]

    return <mergeFile>{$in/..,$var1//ItemName[. eq $in]/following-sibling::InventoryQuantity}</mergeFile>
    }</merge>

let $CurrentInventoryValue:=<mergeInventory>{for $item in $mergeInvertory/mergeFile
    return <INVENTORY><ItemName>{$item//ItemName}</ItemName><UnitPrice>{data($item//UnitPrice)}</UnitPrice><InventoryQuantity>{$item//InventoryQuantity}</InventoryQuantity><TotalInventoryQuantity>{$item//UnitPrice * sum($item//InventoryQuantity)}</TotalInventoryQuantity></INVENTORY>
    }</mergeInventory>
return $CurrentInventoryValue
票数 1
EN

Stack Overflow用户

发布于 2019-09-10 18:50:12

ItemName在库存中只出现一次吗?每个ItemName值是否只出现在一个库存中?如果是这样的话,您可以使用包含cts:*-co-occurrences函数的范围索引来获取两个“表”,然后将它们相乘。

代码语言:javascript
代码运行次数:0
运行
复制
let $itemQuantities := cts:element-value-co-occurrences(
  xs:QName('ItemName'),
  xs:QName('InventoryQuantity'),
  'map',
  cts:collection-query('Inventory')
)

let $itemPrices := cts:element-value-co-occurrences(
  xs:QName('ItemName'),
  xs:QName('UnitPrice'),
  'map',
  cts:collection-query('Item')
)

return fn:sum(
  for $itemName in map:keys($itemQuantities)
  return map:get($itemQuantities, $itemName) * map:get($itemPrices, $itemName)
)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57871156

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档