在XQuery中更新计数器

Gop*_*kur 13 xquery marklogic

我想在xquery中创建一个计数器.我最初的尝试看起来如下:

let $count := 0
for $prod in $collection
let $count := $count + 1
return 
<counter>{$count }</counter>
Run Code Online (Sandbox Code Playgroud)

预期结果:

<counter>1</counter>
<counter>2</counter>  
<counter>3</counter>
Run Code Online (Sandbox Code Playgroud)

实际结果:

<counter>1</counter>
<counter>1</counter>  
<counter>1</counter>
Run Code Online (Sandbox Code Playgroud)

$count变量或者未能更新或处于复位状态.为什么我不能重新分配现有变量?什么是获得理想结果的更好方法?

toh*_*ohu 22

尝试使用'at':

for $d at $p in $collection
return 
element counter { $p }
Run Code Online (Sandbox Code Playgroud)

这将为您提供每个'$ d'的位置.如果要与order by子句一起使用它,这将不起作用,因为位置基于初始顺序,而不是排序结果.为了克服这个问题,只需将FLWOR表达式的排序结果保存在变量中,并at在第二个FLWOR中使用该子句,该FLWOR只迭代第一个排序结果.

let $sortResult := for $item in $collection
                   order by $item/id
                   return $item

for $sortItem at $position in $sortResult
return <item position="{$position}"> ... </item>
Run Code Online (Sandbox Code Playgroud)


Leo*_*ler 9

正如@Ranon所说,所有XQuery值都是不可变的,因此您无法更新变量.但是如果你真的需要一个可更新的数字(不应该太频繁),你可以使用递归:

declare function local:loop($seq, $count) {
  if(empty($seq)) then ()
  else
    let $prod  := $seq[1],
        $count := $count + 1
    return (
      <count>{ $count }</count>,
      local:loop($seq[position() > 1], $count)
    )
};

local:loop($collection, 0)
Run Code Online (Sandbox Code Playgroud)

这与您的示例完全一样.

XQuery 3.0中,甚至在标准库中定义了此函数的更通用版本:fn:fold-right($ f,$ zero,$ seq)

也就是说,在你的例子中,你绝对应该使用at $count@tohuwawohu所示.


Jen*_*rat 6

不可变的变量

XQuery是一种函数式编程语言,其中包含不可变变量,因此您无法更改变量的值.另一方面,您可以使用功能强大的函数集,从而解决了许多日常编程问题.

let $count := 0
for $prod in $collection]
  let $count := $count + 1
return 
<counter>{$count }</counter>
Run Code Online (Sandbox Code Playgroud)

let $count第1行定义了所有范围内的变量,在这种情况下都是以下行.let $count第3行定义了一个新的$count,它在此代码块0+1中的所有后续行中有效- 未定义.所以你确实增加了三倍,但立即丢弃了结果.$count

BaseX的查询信息显示了此查询的优化版本

for $prod in $collection
  return element { "counter" } { 1 }
Run Code Online (Sandbox Code Playgroud)

解决方案

要获得元素的总数$collection,您可以使用

return count($collection)
Run Code Online (Sandbox Code Playgroud)

有关XQuery函数的列表,您可以查看functxXQuery部分,其中包含XQuery函数列表以及一些其他有用的函数,这些函数可以作为模块包含在内.


wca*_*lon 6

上面的所有解决方案都是有效的,但我想提一下,您可以使用XQuery Scripting扩展来设置变量值:

variable $count := 0;

for $prod in (1 to 10)
return {
  $count := $count + 1;
  <counter>{$count}</counter>
}
Run Code Online (Sandbox Code Playgroud)

你可以在http://www.zorba-xquery.com/html/demo#twh+3sJfRpHhZR8pHhOdsmqOTvQ=上试试这个例子.

  • 这是一个XQuery 3.0的东西吗?可能还不错. (2认同)
  • XQuery Scripting是一些XQuery实现提供的扩展.如果您想同时执行更新和返回元素(例如,对于Web服务),则会特别好,但会阻止大量可能的优化.你应该尽可能坚持基本的XQuery. (2认同)

mbl*_*ele 6

具体到MarkLogic,您也可以使用xdmp:set.但这打破了功能语言的假设,因此保守地使用它.

http://docs.marklogic.com/5.0doc/docapp.xqy#display.xqy?fname=http://pubs/5.0doc/apidoc/ExsltBuiltins.xml&category=Extension&function=xdmp:set

有关xdmp:set实际代码的示例,搜索解析器https://github.com/mblakele/xqysp/blob/master/src/xqysp.xqy可能会有所帮助.