使用tokenize和match在xquery中进行多个关键字搜索

时间:2016-10-21 12:37:33

标签: xquery xquery-3.0

我之前尝试过这个问题显然太复杂了,再试一次! 我正在编写Xquery中的搜索。在其中一个字段(标题)中,应该可以输入多个关键字。目前只有一个关键字有效。当存在多个错误时,会出现错误错误XPTY0004:参数1的实际基数与函数签名中声明的基数不匹配:concat($ atomizable-values as xs:anyAtomicType?,. ..)xs:string?。预期基数:零或一,得到2.

在我的xquery中,我试图通过\ s对关键字进行标记,然后单独匹配它们。我认为这种方法可能是假的,但我不确定使用其他方法。我显然是初学者!!

以下是要搜索的示例XML:

<files>

<file>
<identifier>
    <institution>name1</institution>
    <idno>signature</idno>
</identifier>
<title>Math is fun</title>
</file>

<file>
<identifier>
    <institution>name1</institution>
    <idno>signature1</idno>
</identifier>
<title>philosophy of math</title>
</file>

<file>
<identifier>
    <institution>name2</institution>
    <idno>signature2</idno>
</identifier>
<title>i like cupcakes</title>
</file>

</files>

这是Xquery的示例输入&#39; math&#39;对于搜索字段标题和&#39; name1&#39;对于搜索领域机构。 这是有效的,搜索输出是标题&#39;数学很有趣&#39;和数学哲学&#39;。如果您将输入($ title)更改为“数学有趣”,那么无效的方法是什么。然后你会收到错误信息。所需的输出是标题&#39;数学很有趣&#39;

xquery version "3.0";

let $institution := 'name1'
let $title := 'math' (:change to 'math fun' and doesn't work anymore, only a single word works:)


let $title-predicate := 
if ($title)
 then
    if (contains($title, '"'))
    then concat("[contains(lower-case(title), '", replace($title, '["]', ''), "')]")  (:This works fine:)
    else
    for $title2 in tokenize($title, '\s') (:HERE IS THE PROBLEM, this only works when the input is a single word, for instance 'math' not 'math fun':)
    return
    concat("[matches(lower-case(title), '", $title2, "')]")
else ()


let $institution-predicate := if ($institution) then concat('[lower-case(string-join(identifier/institution))', " = '", $institution, "']") else ()


let $eval-string := concat
("doc('/db/Unbenannt.xml')//file", 
$institution-predicate,
$title-predicate
)


let $records := util:eval($eval-string) 
let $test := count($records)
let $content :=

                        <inner_container>
                            <div>
                                <h2>Search Results</h2>

                              <ul>
                               {
                              for $record in $records
                              return
                                <li id="searchList">  
                                <span>{$record//institution/text()}</span> <br/>
                                <span>{$record//title/text()}</span>
                                </li>
                                }
                              </ul>
                            </div>
                            </inner_container>

return 
$content

2 个答案:

答案 0 :(得分:1)

您必须使用string-join()包装FLWOR表达式:

string-join(
    for $title2 in tokenize($title, '\s')
    return
    concat("[matches(lower-case(title), '", $title2, "')]")
)

答案 1 :(得分:0)

如果tokenize($title)返回字符串序列,则

for $title2 in tokenize($title, '\s')
return concat("[matches(lower-case(title), '", $title2, "')]")

也会返回一串字符串

因此$title-predicate将是一个字符串序列,并且您不能提供一系列字符串作为concat()的参数之一。

所以很清楚什么是错的,但修复它需要更深入地了解你的查询,而不是我有时间去获取。

我发现很难相信将查询生成为字符串然后对该查询进行动态评估的方法确实是必要的。