Marklogic 具有相同约束名称、不同名称空间的多个约束

Marklogic 具有相同约束名称、不同名称空间的多个约束,marklogic,Marklogic,根据搜索开发者指南: 每个约束都已命名,并且名称在“选项”节点中的所有运算符和约束中必须是唯一的 我们使用的是一个内容丰富包,其输出如下: `<TM360:Measurements Measurements="Distance"> <Measurements:Distance Amount="3" Unit="inches"/> </TM360:Measurements> <TM360:Measurements Measurements="Vol

根据搜索开发者指南: 每个约束都已命名,并且名称在“选项”节点中的所有运算符和约束中必须是唯一的

我们使用的是一个内容丰富包,其输出如下:

`<TM360:Measurements Measurements="Distance">
    <Measurements:Distance Amount="3" Unit="inches"/>
</TM360:Measurements>
<TM360:Measurements Measurements="Volume">
    <Measurements:Volume Amount="5.0" Unit="liters"/>
</TM360:Measurements>`
<dist:inches xmlns:dist="ns://fubar.distance">3</dist:inches>
<vol:liters xmlns:vol="ns://fubar.volume">5.0</vol:liters>
`
`
查看“金额”: 属性localName不是唯一的,但包含它的元素是唯一的

有没有办法绕过约束名称唯一性限制来构建一个约束搜索,比如“Amount:5.0”,该搜索将包括上面两个条目上的索引


处理这种情况的最佳方法是什么?

为了获得最佳结果,您必须重构或丰富XML。搜索API旨在充分利用MarkLogic基于QName的索引功能。现在的XML只有一个元素QName:TM360和几个属性QName,它们都不是强选择性的

您可以使用XSLT或递归转换来重新格式化该XML。我建议你瞄准这样的目标:

`<TM360:Measurements Measurements="Distance">
    <Measurements:Distance Amount="3" Unit="inches"/>
</TM360:Measurements>
<TM360:Measurements Measurements="Volume">
    <Measurements:Volume Amount="5.0" Unit="liters"/>
</TM360:Measurements>`
<dist:inches xmlns:dist="ns://fubar.distance">3</dist:inches>
<vol:liters xmlns:vol="ns://fubar.volume">5.0</vol:liters>
3
5
作为一个副作用,这允许您编写更简洁的XPath查询,并允许为节点提供更具体的模式类型


这个用例可能是有计划的,但是你也可以考虑把所有这些度量标准化成SI单位的标准子集,比如,比较比较容易。

对于最好的结果,你必须重构或丰富XML。搜索API旨在充分利用MarkLogic基于QName的索引功能。现在的XML只有一个元素QName:TM360和几个属性QName,它们都不是强选择性的

您可以使用XSLT或递归转换来重新格式化该XML。我建议你瞄准这样的目标:

`<TM360:Measurements Measurements="Distance">
    <Measurements:Distance Amount="3" Unit="inches"/>
</TM360:Measurements>
<TM360:Measurements Measurements="Volume">
    <Measurements:Volume Amount="5.0" Unit="liters"/>
</TM360:Measurements>`
<dist:inches xmlns:dist="ns://fubar.distance">3</dist:inches>
<vol:liters xmlns:vol="ns://fubar.volume">5.0</vol:liters>
3
5
作为一个副作用,这允许您编写更简洁的XPath查询,并允许为节点提供更具体的模式类型


这个用例可能是有计划的,但是你也可以考虑把所有这些度量标准化成SI单位的标准子集,比如,比较比较容易。

你可以创建一个自定义约束来实现这一点。我使用以下三个脚本成功地做到了这一点:

  • setup-db.xqy
  • search.xqy
  • 自定义约束.xqy
下面是安装脚本,它创建了两个“Amount”范围索引,并添加了两个示例文档(test1.xml和test2.xml):

最后,这里是custom-constraint.xqy代码,它将约束文本转换为跨两个数量索引的cts或查询:

xquery version "1.0-ml";

module namespace my = "http://example.com/custom-constraint";

declare namespace Measurements = "http://example.com/Measurements";

declare default function namespace "http://www.w3.org/2005/xpath-functions";

(: Convert the constraint text into an OR query against "Distance" and "Volume" :)
declare function my:parse-amount($constraint-qtext as xs:string,
                                 $right as schema-element(cts:query))
        as schema-element(cts:query)
{
  let $value := xs:decimal($right//cts:text)
  return
    <cts:or-query>{
      my:make-amount-query("Distance",$value),
      my:make-amount-query("Volume"  ,$value)
    }</cts:or-query>
};


declare function my:make-amount-query($parent-name, $value) {
  cts:element-attribute-range-query(
    (: parent name    :) QName("http://example.com/Measurements", $parent-name),
    (: attribute name :) xs:QName("Amount"),
    (: operator       :) "=",
    (: value          :) $value
  )
};
xquery版本“1.0-ml”;
模块名称空间my=”http://example.com/custom-constraint";
声明命名空间度量值=”http://example.com/Measurements";
声明默认函数名称空间“http://www.w3.org/2005/xpath-functions";
(:将约束文本转换为或查询“距离”和“体积”:
将函数my:parse amount($constraint qtext)声明为xs:string,
$right作为模式元素(cts:query))
作为模式元素(cts:query)
{
让$value:=xs:decimal($right//cts:text)
回来
{
my:进行金额查询(“距离”,美元值),
我的:进行金额查询(“卷”,美元值)
}
};
声明函数my:进行金额查询($parent name,$value){
元素属性范围查询(
(:父名称:)QName(“http://example.com/Measurements“,$parent name),
(:属性名称:)xs:QName(“金额”),
(:运算符:)“=”,
(:value:)$value
)
};

如果您希望约束也作为一个方面发挥作用,那么您还需要实现start facet和finish facet函数(并相应地扩展选项节点中的定义。包括如何执行此操作的示例。

您可以创建自定义约束以实现此目的。我使用以下三个脚本成功地完成了此操作:

  • setup-db.xqy
  • search.xqy
  • 自定义约束.xqy
下面是安装脚本,它创建了两个“Amount”范围索引,并添加了两个示例文档(test1.xml和test2.xml):

最后,这里是custom-constraint.xqy代码,它将约束文本转换为跨两个数量索引的cts或查询:

xquery version "1.0-ml";

module namespace my = "http://example.com/custom-constraint";

declare namespace Measurements = "http://example.com/Measurements";

declare default function namespace "http://www.w3.org/2005/xpath-functions";

(: Convert the constraint text into an OR query against "Distance" and "Volume" :)
declare function my:parse-amount($constraint-qtext as xs:string,
                                 $right as schema-element(cts:query))
        as schema-element(cts:query)
{
  let $value := xs:decimal($right//cts:text)
  return
    <cts:or-query>{
      my:make-amount-query("Distance",$value),
      my:make-amount-query("Volume"  ,$value)
    }</cts:or-query>
};


declare function my:make-amount-query($parent-name, $value) {
  cts:element-attribute-range-query(
    (: parent name    :) QName("http://example.com/Measurements", $parent-name),
    (: attribute name :) xs:QName("Amount"),
    (: operator       :) "=",
    (: value          :) $value
  )
};
xquery版本“1.0-ml”;
模块名称空间my=”http://example.com/custom-constraint";
声明命名空间度量值=”http://example.com/Measurements";
声明默认函数名称空间“http://www.w3.org/2005/xpath-functions";
(:将约束文本转换为或查询“距离”和“体积”:
将函数my:parse amount($constraint qtext)声明为xs:string,
$right作为模式元素(cts:query))
作为模式元素(cts:query)
{
让$value:=xs:decimal($right//cts:text)
回来
{
my:进行金额查询(“距离”,美元值),
我的:进行金额查询(“卷”,美元值)
}
};
声明函数my:进行金额查询($parent name,$value){
元素属性范围查询(
(:父名称:)QName(“http://example.com/Measurements“,$parent name),
(:属性名称:)xs:QName(“金额”),
(:运算符:)“=”,
(:value:)$value
)
};

如果您希望约束也作为一个方面发挥作用,那么您还需要实现start facet和finish facet函数(并相应地增加选项节点中的定义。包括如何执行此操作的示例。

使用cts函数将相对简单。您可以执行以下操作:

declare namespace Measurements = "http://example.com/Measurements";

cts:search(doc(), cts:element-attribute-value-query(
  (xs:QName("Measures:Distance"), xs:QName("Measures:Volume")),
  xs:QName("Amount"),
  $myamount
))
幸运的是,从MarkLogic 8.0-5开始,您还可以将其表示为单个搜索约束,并将其与
search:search
或(现在)内置REST api一起使用:

xquery version "1.0-ml";

declare namespace TM360        = "http://example.com/TM360";
declare namespace Measurements = "http://example.com/Measurements";

xdmp:document-insert(
  "/amount3.xml",
  <TM360:Measurements Measurements="Distance">
    <Measurements:Distance Amount="3" Unit="inches"/>
  </TM360:Measurements>
),
xdmp:document-insert(
  "/amount5.xml",
  <TM360:Measurements Measurements="Volume">
    <Measurements:Volume Amount="5.0" Unit="liters"/>
  </TM360:Measurements>
)

;

import module namespace search="http://marklogic.com/appservices/search"
       at "/MarkLogic/appservices/search/search.xqy";

declare variable $options :=
  <options xmlns="http://marklogic.com/appservices/search">
    <constraint name="Amount">
      <value>
        <element ns="http://example.com/Measurements" name="Distance"/>
        <element ns="http://example.com/Measurements" name="Volume"/>
        <attribute ns="" name="Amount"/>
      </value>
    </constraint>
  </options>;

(: matches /amount3.xml :)
search:search("Amount:3",$options),

(: matches /amount5.xml :)
search:search("Amount:5.0",$options)
xquery版本“1.0-ml”;
声明命名空间TM360=“http://