Marklogic 搜索内的命名空间声明:搜索选项节点在2+;为同一URI声明前缀

Marklogic 搜索内的命名空间声明:搜索选项节点在2+;为同一URI声明前缀,marklogic,marklogic-8,Marklogic,Marklogic 8,MarkLogic版本:8.0-3.2 如果一个search:search选项节点(如)中有多个名称空间声明,且前缀不同,但URI相同,则除第一个前缀外的所有前缀都会在search:search调用中丢失 这是预期的行为吗?它在ML7.0-4.3中不存在,而且我不知道在不同前缀下对同一名称空间uri的多个声明违反了XML名称空间或xQuery规范 任何洞察都是值得赞赏的 测试设置脚本: (:~ :两项交易: :(1)在“文档”数据库中的元素{myuri:baz}子元素上创建元素范围索引 :(2)

MarkLogic版本:8.0-3.2

如果一个search:search选项节点(如
)中有多个名称空间声明,且前缀不同,但URI相同,则除第一个前缀外的所有前缀都会在search:search调用中丢失

这是预期的行为吗?它在ML7.0-4.3中不存在,而且我不知道在不同前缀下对同一名称空间uri的多个声明违反了XML名称空间或xQuery规范

任何洞察都是值得赞赏的

测试设置脚本:
(:~
:两项交易:
:(1)在“文档”数据库中的元素{myuri:baz}子元素上创建元素范围索引
:(2)在/baz/test/test-baz.xml插入测试文档
:
:预期输出:空序列
:)
(:事务(1):设置索引:)
xquery版本“1.0-ml”;
导入模块命名空间管理=”http://marklogic.com/xdmp/admin“在“/MarkLogic/admin.xqy”;
让$config:=admin:get-configuration(),
$dbid:=xdmp:数据库(“文档”),
$rangespec:=管理员:数据库范围元素索引(“字符串”、“myuri:baz”、“子项”、”http://marklogic.com/collation/,fn:false(),“拒绝”)
返回
试一试{
管理员:保存配置而不重新启动(
管理员:数据库添加范围元素索引($config、$dbid、$rangespec)
)
}捕获量(e美元){
“索引已存在?请检查日志。”,
xdmp:log($e,“调试”)
}
;
(:事务(2):插入测试文档:)
xquery版本“1.0-ml”;
声明名称空间baz=“myuri:baz”;
让$uri:=“/baz/test/test baz.xml”,
$document:=
试验
返回
xdmp:文档插入($uri,$document)
测试脚本(为了清晰/可读性而冗长):
xquery版本“1.0-ml”;
导入模块命名空间搜索=”http://marklogic.com/appservices/search“在“/MarkLogic/appservices/search/search.xqy”;
(:附加查询:xmlns:foo优先,xmlns:bar第二;cts:element:foo:child.successed.:)
声明变量$search-options-1:=
())、(“分数logtfidf”、cts:score order(“降序”)、xs:double(“1”)、())--没有子元素的字符串元素范围索引

通过

XDMP-ELEMRIDXNOTFOUND:cts:search(fn:collection()、cts:and query(cts:element-range-query(xs:QName(“foo:child”)、“=”、“TEST”(“collation=”)、(“collation=”)、(“collation=”)、(“score-logtfidf”、cts:score-order(“descending”)、xs:double(“1”)、())无子元素范围索引

更新:当祖先多次在不同前缀下声明同一命名空间URI时,元素级命名空间声明(w/direct构造函数或通过fn:QName()序列化)也会在ML8(而不是ML7)下中断 前缀在self中丢失::*当任何祖先在不同前缀下多次声明相同URI时:

xquery version "1.0-ml";

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

(: Serialize namespace w/ fn:QName(), no namespace inheritance: PASS :)
declare variable $search-options-1 :=
  <options xmlns="http://marklogic.com/appservices/search">
    <additional-query>
      <cts:element-range-query operator="=">
        <cts:element>{fn:QName("myuri:baz", "child")}</cts:element>
        <cts:value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">TEST</cts:value>
      </cts:element-range-query>
    </additional-query>
  </options>;

(: Serialize namespace w/ fn:QName(), namespace inheritance, declared once: PASS :)
declare variable $search-options-2 :=
  <options xmlns="http://marklogic.com/appservices/search">
    <additional-query xmlns:foo="myuri:baz">
      <cts:element-range-query operator="=">
        <cts:element>{fn:QName("myuri:baz", "child")}</cts:element>
        <cts:value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">TEST</cts:value>
      </cts:element-range-query>
    </additional-query>
  </options>;

(: Serialize namespace w/ fn:QName(), namespace inheritance, declared twice: FAIL :)
declare variable $search-options-3 :=
  <options xmlns="http://marklogic.com/appservices/search">
    <additional-query xmlns:foo="myuri:baz" xmlns:bar="myuri:baz">
      <cts:element-range-query operator="=">
        <cts:element>{fn:QName("myuri:baz", "child")}</cts:element>
        <cts:value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">TEST</cts:value>
      </cts:element-range-query>
    </additional-query>
  </options>;

for $search-options in ($search-options-1, $search-options-2, $search-options-3)
return
    try {
        let $test := search:search("", $search-options, 1) instance of element(search:response)
        return
            if ($test) then "PASS"
            else "FAIL" (: won't reach :)
    } catch($e) {
        $e/error:format-string/fn:string(.)
    }
xquery版本“1.0-ml”;
导入模块命名空间搜索=”http://marklogic.com/appservices/search“在“/MarkLogic/appservices/search/search.xqy”;
(:序列化命名空间w/fn:QName(),无命名空间继承:PASS:)
声明变量$search-options-1:=

),(“分数logtfidf”,cts:score order(“降序”),,xs:double(“1”),()--没有子元素的字符串元素范围索引

我相信搜索API一直都有这个限制。我同意令人惊讶的是,这是不幸的——标准并不支持这一限制——但是,通过为每个名称空间uri使用一个且仅使用一个前缀,您是否很难绕过这一限制?如果没有其他内容,这会使声明更简单。

如果您在XQuery上下文中直接使用搜索API,则可以使用
fn:QName()
来获得元素QName的一致序列化:

<cts:element>{ fn:QName("myuri:baz", "child") }</cts:element>
评估结果为:

<cts:element xmlns:_1="myuri:baz">_1:child</cts:element>
<cts:element xmlns:foo="myuri:baz">foo:child</cts:element>
foo:child

当然,如果将REST API与存储的搜索选项一起使用,这种方法将毫无帮助。

我可以确认它在7.0-5.1中运行,但在8.0-4中不运行。我已经在内部报告这是一个bug

看起来处理其他查询的方式已更改。但是如果将名称空间声明向下移动两个元素中的一个,则不会出现任何错误。也许这对你来说是一个有用的解决方法


感谢ehennum和jofemfb的建议,这两个建议都很有意义。我应该在我的问题中澄清一下,我并没有寻找太多的变通方法或解决方案,但我想知道这是否是ML8中的一个bug。上述行为在ML7.0-4.3中不存在(更新了问题以反映这一点已经过测试)。感谢测试用例。预计8.0-5将有一个修复。Joe,感谢您的评论。我在上面的问题中添加了一个更新,以表明当任何祖先多次声明同一名称空间时,在self::*级别重新声明名称空间(通过fn:QName()序列化或作为直接构造函数)也会中断。我同意你和Erik的观点,最明显的解决方案是不要随意多次过度使用你的名称空间,但是由于ML7中没有出现这种行为,我仍然认为我们在这里看到了一些错误。如果有兴趣,请参阅上面的问题“更新:元素级命名空间声明[…]”。谢谢,Geert。我可以通过自己的测试确认这种行为似乎与名称空间继承有关:在树的更深处声明名称空间是正确的。(推测:我相信在一个内置模块中的某个地方,我们可能正在使用附加查询中声明的名称空间的URI值作为键生成一个映射,这就是我们可能会丢失冗余声明前缀的方式。我模糊地记得在过去看到过这一点,但现在很难重新定位它。)
<cts:element xmlns:_1="myuri:baz">_1:child</cts:element>
declare namespace foo ="myuri:baz";
<cts:element>{ xs:QName("foo:child") }</cts:element>
<cts:element xmlns:foo="myuri:baz">foo:child</cts:element>