需求:
这个需求是这样的:对于双引号的Phrase需要进行精确的查询。例如:
Query text为:
Marklogic is “enterprise NoSql” solution.
Search:parse结果:
我们发现在做完search:parse后得到:
search:parse('Marklogic is "enterprise NoSql"solution')
return
<cts:and-query strength="20" qtextjoin=""qtextgroup="( )" xmlns:cts="http://marklogic.com/cts">
<cts:word-queryqtextref="cts:text">
<cts:text>Marklogic</cts:text>
</cts:word-query>
<cts:and-querystrength="20" qtextjoin="" qtextgroup="( )">
<cts:word-queryqtextref="cts:text">
<cts:text>is</cts:text>
</cts:word-query>
<cts:and-querystrength="20" qtextjoin="" qtextgroup="( )">
<cts:word-query qtextpre="""qtextref="cts:text" qtextpost=""">
<cts:text>enterprise NoSql</cts:text>
</cts:word-query>
<cts:word-query qtextref="cts:text">
<cts:text>solution</cts:text>
</cts:word-query>
</cts:and-query>
</cts:and-query>
</cts:and-query>
我们看到”enterpriseNoSql”作为一个phrase进行查询。是没有问题的。
问题QueryText:
Marklogic is “document” solution
Search:parse结果:
我们发现在做完search:parse后得到:
search:parse('Marklogic is "document" solution')
<cts:and-query strength="20"qtextjoin="" qtextgroup="( )"xmlns:cts="http://marklogic.com/cts">
<cts:word-queryqtextref="cts:text">
<cts:text>Marklogic</cts:text>
</cts:word-query>
<cts:and-querystrength="20" qtextjoin="" qtextgroup="( )">
<cts:word-queryqtextref="cts:text">
<cts:text>is</cts:text>
</cts:word-query>
<cts:and-querystrength="20" qtextjoin="" qtextgroup="( )">
<cts:word-queryqtextpre=""" qtextref="cts:text"qtextpost=""">
<cts:text>document</cts:text>
</cts:word-query>
<cts:word-query qtextref="cts:text">
<cts:text>solution</cts:text>
</cts:word-query>
</cts:and-query>
</cts:and-query>
</cts:and-query>
问题:
你会发现document转化为的word-query与其它的word-query基本一致。这里就会有潜在的问题了。
如果当下我们的searchoption设置的是stemmed。那么该document查询过程中就会使用到了stemmed。
因此你会得到诸如documents,document的变体查询结果。这个是不允许的。因为用户想要对双引号内的term做精确查询。
方案:
有上面获得的parse结果来看,思路就是:如果这个word-query有前置,及后置双引号,那么我们需要人工干预,给该word-query加一个unstemmedoption.
<cts:word-query qtextpre=""" qtextref="cts:text"qtextpost=""">
<cts:text>document</cts:text>
</cts:word-query>
变形后:
<cts:word-queryqtextpre=""" qtextref="cts:text"qtextpost=""">
<cts:text>document</cts:text>
<cts:option>unstemmed</cts:option>
</cts:word-query>
具体实现:
1:使用search:prase
获得cts:query解析xml结构对象,以便于处理其中的word-query对象。
2:使用xdmp:set
实行过程中,使用了xdmp:set毫无疑问是用来处理变量的。当我们加入设置了新的option,需要把该变换影射到cts:query变量上
3:使用search:resolve
用它来执行你的结构化cts:query (search:search用来执行querytext)
源代码:
直接顺序替代。发现目标---〉替换目标。整个迭代过程由orginalelement进行。
declare namespacects="http://marklogic.com/cts";
declare function local:copy-replace($elementas element()) {
if ($element/self::cts:word-query) (判断替换条件)
then
(
if($element/@qtextpre="""and $element/@qtextpost=""")then
(
<root>{
cts:and-query((
cts:or-query((
cts:element-word-query(fn:QName("http://www.wolterskluver.com/namespace/meta","DocTitle"),$element//cts:text/text(),("unstemmed","case-insensitive"),16),
cts:element-query(fn:QName("http://www.wolterskluver.com/namespace/meta","Meta"),cts:word-query($element//cts:text/text(),("unstemmed","case-insensitive"),2)),
cts:word-query($element//cts:text/text(),("unstemmed","case-insensitive"),1)
))
))
}</root>/*
)
else
(
<root>{
cts:and-query((
cts:or-query((
cts:element-word-query(fn:QName("http://www.wolterskluver.com/namespace/meta","DocTitle"),$element//cts:text/text(), "case-insensitive",16),
cts:element-query(fn:QName("http://www.wolterskluver.com/namespace/meta","Meta"),cts:word-query($element//cts:text/text(),"case-insensitive",2)),
cts:word-query($element//cts:text/text(),"case-insensitive",1)
))
))
}</root>/*
)
)
else element {node-name($element)}
{$element/@*,
for $childin $element/node()
return if ($child instance of element())
then local:copy-replace($child)
else $child
}
};
let $query:=search:parse('abc "SUPPLEMENT" ABC')
return
(
local:copy-replace($query),
search:resolve(local:copy-replace($query))
)
结果输出:
<?xml version="1.0" encoding="UTF-8"?>
<cts:and-query strength="20"qtextjoin="" qtextgroup="( )"xmlns:cts="http://marklogic.com/cts">
<cts:and-query>
<cts:or-query>
<cts:element-word-queryweight="16">
<cts:elementxmlns:_1="http://www.wolterskluver.com/namespace/meta">_1:DocTitle</cts:element>
<cts:textxml:lang="en">abc</cts:text>
<cts:option>case-insensitive</cts:option>
</cts:element-word-query>
<cts:element-query>
<cts:elementxmlns:_1="http://www.wolterskluver.com/namespace/meta">_1:Meta</cts:element>
<cts:word-queryweight="2">
<cts:textxml:lang="en">abc</cts:text>
<cts:option>case-insensitive</cts:option>
</cts:word-query>
</cts:element-query>
<cts:word-query>
<cts:textxml:lang="en">abc</cts:text>
<cts:option>case-insensitive</cts:option>
</cts:word-query>
</cts:or-query>
</cts:and-query>
<cts:and-querystrength="20" qtextjoin="" qtextgroup="( )">
<cts:and-query>
<cts:or-query>
<cts:element-word-queryweight="16">
<cts:element xmlns:_1="http://www.wolterskluver.com/namespace/meta">_1:DocTitle</cts:element>
<cts:textxml:lang="en">SUPPLEMENT</cts:text>
<cts:option>case-insensitive</cts:option>
<cts:option>unstemmed</cts:option>
</cts:element-word-query>
<cts:element-query>
<cts:elementxmlns:_1="http://www.wolterskluver.com/namespace/meta">_1:Meta</cts:element>
<cts:word-query weight="2">
<cts:textxml:lang="en">SUPPLEMENT</cts:text>
<cts:option>case-insensitive</cts:option>
<cts:option>unstemmed</cts:option>
</cts:word-query>
</cts:element-query>
<cts:word-query>
<cts:textxml:lang="en">SUPPLEMENT</cts:text>
<cts:option>case-insensitive</cts:option>
<cts:option>unstemmed</cts:option>
</cts:word-query>
</cts:or-query>
</cts:and-query>
<cts:and-query>
<cts:or-query>
<cts:element-word-queryweight="16">
<cts:elementxmlns:_1="http://www.wolterskluver.com/namespace/meta">_1:DocTitle</cts:element>
<cts:textxml:lang="en">ABC</cts:text>
<cts:option>case-insensitive</cts:option>
</cts:element-word-query>
<cts:element-query>
<cts:elementxmlns:_1="http://www.wolterskluver.com/namespace/meta">_1:Meta</cts:element>
<cts:word-query weight="2">
<cts:textxml:lang="en">ABC</cts:text>
<cts:option>case-insensitive</cts:option>
</cts:word-query>
</cts:element-query>
<cts:word-query>
<cts:textxml:lang="en">ABC</cts:text>
<cts:option>case-insensitive</cts:option>
</cts:word-query>
</cts:or-query>
</cts:and-query>
</cts:and-query>
</cts:and-query>