1

我是 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

这是不正确的,显然。有什么帮助使它正确吗?

4

1 回答 1

2

最简单的模式如下,为每个可能的请求参数创建变量(为每个请求参数提供一个默认值作为空序列),然后在 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)为区分大小写的文字字符串匹配、matches(title, $title, 'i')不区分大小写的正则表达式搜索或全文索引,例如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 子句中的比较。此代码假定每个参数最多一个值;如果您允许每个参数有多个值,则需要进行一些调整。

于 2016-12-24T04:51:08.387 回答