【问题标题】:How to remove duplicate results from a cts:uris when distinct values does not work当不同的值不起作用时如何从 cts:uris 中删除重复的结果
【发布时间】:2019-04-25 18:43:43
【问题描述】:

我有以下代码返回结果数组我尝试使用 distinct-values 删除重复项,但它什么也没做我也尝试使用循环函数通过比较值来删除但没有成功。

我尝试转换为“xs anyAtomicType”并使用不同的值 我尝试放入 json 数组并提取子数组 我尝试过标记化、xdmp 引用、字符串之前/之后以及许多其他方法

declare function local:verify-user-uri($dir as xs:string) 
{ 
   for $each in cts:uris($dir, ())
     let $uIds := (for $d in $each  
     where contains($d, "/profile.xml")
   return $d)

   return $uIds
};    

我以以下形式返回重复的结果:

/users/123-343-/profile.xml
/users/122-222-/profile.xml
/users/123-343-/profile.xml
/users/122-222-/profile.xml
/users/123-343-/profile.xml
/users/122-222-/profile.xml

我期待:

/users/123-343-/profile.xml
/users/122-222-/profile.xml

【问题讨论】:

  • 请包含重现您的问题所需的所有代码。 URI 在数据库中是唯一的,因此您包含的示例没有意义。

标签: duplicates xquery marklogic


【解决方案1】:

有没有可能你只是简单地调用了这个函数 3 次而没有意识到呢?

您已将$dir 声明为单个xs:string。如果您的 $dir 恰好是同一目录的一系列字符串,或者您使用目录变量调用了该函数 3 次。

启用函数映射(默认行为)很容易发生这种情况。 https://docs.marklogic.com/guide/xquery/enhanced#id_55459

您可以做几件事作为诊断:

1.) 移除函数中$dir参数的显式类型:

declare function local:verify-user-uri($dir) 
{ 
   for $each in cts:uris($dir, ())
   let $uIds := (for $d in $each  
     where contains($d, "/profile.xml")
     return $d)
   return $uIds
};

执行cts:uris() 时是否遇到如下错误:

[1.0-ml] XDMP-ARGTYPE: )err:XPT0004) cts:uris(("/users/", "/users/", "/users/"), ()) -- arg1 不是输入 xs:string?

2.) 尝试通过在序言中添加以下内容来禁用函数映射:

declare option xdmp:mapping "false";

然后看看你是否得到一个无效的强制错误,比如:

[1.0-ml] XDMP-AS (err:XPTY0004) $dir as xs:string -- 无效的强制转换 ("/users/", "/users/", "/users/") 作为 xs:string

3.) 您还可以在函数返回的值序列的末尾添加一些内容,以指示它执行了多少次:

declare function local:verify-user-uri($dir as xs:string) 
{ 
   for $each in cts:uris($dir, ())
   let $uIds := (for $d in $each  
     where contains($d, "/profile.xml")
     return $d)
   return $uIds, "#"
};

看看你在结果中看到了多少次“#”。如果不止一个,则表示您正在多次调用该函数。

【讨论】:

  • 谢谢,我会尝试尝试选项建议。对不起 ($dir as xs:string) 我在代码中必须忘记正确复制它
  • 我尝试了以下操作并得到了相同的结果,但结尾多次包含 # ,因为我知道我只调用了一次函数,因为字符串参数只是 dir = “/用户/”
  • let $db := -conf:getOnlineDB() let $test := xdmp:eval('declare option xdmp:mapping "false"; 将变量 $dir 声明为 xs:string external; contains( cts:uris($dir, ()), "/profile.xml")', (xs:QName("dir"), $dir), {xdmp:数据库($db)})
  • /users/123-343-/profile.xml /users/122-222-/profile.xml # /users/123-343-/profile.xml /users/122-222-/ profile.xml # /users/123-343-/profile.xml /users/122-222-/profile.xml #
  • 看起来您正在将一个序列传递给包含;那怎么行?那么 cts:uris($dir)[fn:ends-with (., '/profile.xml')
【解决方案2】:

除了来自 Mads 的好建议之外,我还注意到有关您的代码的其他几点:

  • 迭代$each 没有意义,因为它只包含一个uri。请记住,FLWOR 语句以 return 结尾,它告诉 每个项目的结果应该是什么
  • 注意cts:uris 的第一个参数只标记开始,而不是结束。如果您输入/aaa/,您也会返回/bbb/ 等,但反之则不然。

说实话,我认为您正在寻找 cts:uri-match(),这会将您的功能简化为单线:

declare function local:verify-user-uri($dir as xs:string) { 
  cts:uri-match($dir || "*/profile.xml")
};

HTH!

PS:我确实建议始终按照 Mads 的建议禁用函数映射。它可以防止很多混乱。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-03
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多