2016-12-24 2 views
1

Я новичок в XQuery 3.0 и пытаюсь создать простой алгоритм поиска нескольких фильтров.XQuery алгоритм поиска нескольких фильтров

Что я хочу сделать, проверьте, предоставлен ли параметр, и если да, добавьте его в запрос.

Это то, что я имею в моей голове:

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 

Это неверно, очевидно. Любая помощь, чтобы сделать ее правильной?

ответ

2

Простейший шаблон будет выглядеть следующим образом, создавая переменные для каждого возможного параметра запроса (предоставляя значение по умолчанию для каждой из них как пустую последовательность), а затем в предложении возврата проверяйте наличие каждого параметра, время:

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, запросы на title и album не будут рассмотрены, даже если они были поставлены.

Для цепи их вместе, так что любые и все поставленные параметры опрашиваются, вы могли бы принять следующий подход:

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 оцениваются только при условии предоставления параметров. Этот код предполагает не более одного значения для каждого параметра; некоторые настройки потребуются, если вы допустили несколько значений для каждого параметра.

+0

Спасибо @joewiz, ты мой спаситель :) – yenerunver

+0

Приятно слышать;) – joewiz