XQuery 多过滤器搜索算法

XQuery multi-filter search algorithm

我是 XQuery 3.0 的新手,正在尝试创建一个简单的多过滤器搜索算法。

我想做的是,检查是否提供了参数,如果是,将其添加到查询中。

这是我的想法:

let $query := doc("music.xml")//music/album

if (request:get-parameter('type', false)) then
    let $query := $query[ @type=request:get-parameter('type', '') ]
else
    let $query := $query

if (request:get-parameter('title', false)) then
    let $query := $query[ @title=request:get-parameter('title', '') ]
else
    let $query := $query

if (request:get-parameter('artist', false)) then
    let $query := $query[ @artist=request:get-parameter('artist', '') ]
else
    let $query := $query

这显然是不正确的。有任何帮助使其正确吗?

最简单的模式如下,为每个可能的请求参数创建变量(为每个参数提供默认值作为空序列),然后在 return 子句中,检查每个参数是否存在参数,一次一个:

xquery version "3.0";

let $albums := doc("music.xml")//music/album
let $type := request:get-parameter('type', ())
let $title := request:get-parameter('title', ())
let $artist := request:get-parameter('artist', ())
return
    if ($type) then
        $albums[type = $type]
    else if ($title) then
        $albums[title = $title]
    else if ($artist) then
        $albums[artist = $artist]
    else
        $albums

此代码假定 <type><title><artist><album> 的子元素,并且我们检查提供的参数是否完全匹配。对于区分大小写的文字字符串匹配,您可以将 title = $title 比较更改为 contains(title, $title),对于不区分大小写的正则表达式搜索,可以将 title = $title 比较更改为 contains(title, $title),如果您配置了索引,则可以将全文索引更改为 ft:query(title, $title) <title> 元素等的全文索引

这种方法的缺点是我们已经为影响查询的参数硬编码了严格的优先级顺序。如果提供了 type 参数,即使提供了 titlealbum 上的查询也不会被考虑。

要将它们链接在一起以便查询任何和所有提供的参数,您可以采用以下方法:

xquery version "3.0";

let $albums := 
    <albums>
        <album><type>country</type><title>Holiday Classics</title><artist>Jane</artist></album>
        <album><type>country</type><title>Lonesome Cowboy</title><artist>Jim</artist></album>
        <album><type>country</type><title>Lonesome Holiday</title><artist>Jane</artist></album>
    </albums>//album
let $type := request:get-parameter('type', ())
let $title := request:get-parameter('title', ())
let $artist := request:get-parameter('artist', ())
return
    $albums
        [if ($type) then type = $type else true()]
        [if ($title) then title = $title else true()]
        [if ($artist) then artist = $artist else true()]

我提供示例数据只是为了让我自己和其他测试代码的人确认这有效。 return 子句中的比较仅在提供参数时才进行评估。此代码假定每个参数最多一个值;如果您允许每个参数有多个值,则需要进行一些调整。