我不得不将地理空间搜索功能添加到已经存在的应用程序中,该应用程序使用搜索:搜索API并具有全文搜索和分面搜索。我读过有关扩展Search API的内容,但我现在没有时间。所以,我想我会修改我的代码,以便只做两个结果集的交集(一个由搜索返回:搜索API,另一个由cts:search
返回,允许cts:polygon
搜索) 。不幸的是,交叉点严重降低了执行时间。
是否有更好的方法来优化或加速以下表达式?
$results_fts//search:result[./search:metadata/Vhe eq $geo_results//root/Vhe]
这是我的代码:
declare variable $geo_results :=
let $qr := cts:search(doc(), cts:and-query(($q-geospatial,
cts:word-query("*", ("case-insensitive","whitespace-insensitive","wildcarded","diacritic-insensitive")) )) ) (:Search all * within the polygon:)
return $qr;
declare variable $results_fts :=
let $qrs := search:search($q-text, $options, xs:unsignedLong(xdmp:get-request-field("start","1")), 12000) (:max page length to get all records:)
return $qrs;
declare variable $results :=
let $qrt := if (xdmp:get-request-field("map-code")) then
(:intersect geospatial search with the full text search:)
<search:response>
{ $results_fts//search:result[./search:metadata/Vhe eq $geo_results//root/Vhe] }
{ $results_fts//search:facet }
{ $results_fts//search:qtext }
{ $results_fts//search:metrics }
</search:response>
else $results_fts
return $qrt;
答案 0 :(得分:2)
作为Dave的好建议的脚注,另一种选择是使用search:parse()而不是search:search()在运行cts:search之前将第二个搜索请求转换为cts:query ()。
http://docs.marklogic.com/search:parse?q=search:parse&v=8.0&api=true
然后,将cts:query()生成的search:parse()添加到现有cts:and-query()中的子查询列表中,并运行单个搜索。
我不清楚地理空间查询中的cts:word-query(&#34; *&#34;)子句是做什么的,但这与主要点无关。
答案 1 :(得分:1)
Lenti,你正在运行的XPath谓词是比较每一个搜索:结果与每个$ geo_results Vhe相对应 - 可能需要做很多工作,具体取决于找到多少个地理结果。我认为你可能高估了扩展Search API所需的工作量。如果您采用这种方式,MarkLogic可以为您处理优化。
您需要的是自定义约束。您只需要实现解析功能,而不是开始和结束(您需要自定义方面)。看起来你正在使用字符串查询而不是结构化查询,所以像这样:
declare function geo:parse(
$constraint-qtext as xs:string,
$right as schema-element(cts:query))
as schema-element(cts:query)
{
(: TODO: you don't show above how you construct the geospatial query,
: but do that here using $right//cts:text as input.
:)
(: If MarkLogic complains that your geospatial query doesn't match
: the return type, you probably need to serialize it like this:
return <root>{$q-geospatial}</root>/*
:)
};
您还可以在Search API选项中设置约束:
<constraint name="my-custom">
<custom facet="false">
<parse apply="parse" ns="..." at="..." />
</custom>
</constraint>
...其中ns是“geo:”是上面的前缀的命名空间,at是定义解析函数的库模块的路径。
资源:
答案 2 :(得分:0)
除了Dave和Eriks的建议之外,你还可以做与Erik建议相反的事情:采取cts:查询cts:search,并将其作为附加查询嵌入到搜索的搜索选项中:搜索。您可以在运行时为此重新创建$选项。这样做可以让您利用搜索库提供的所有好处。
HTH!
答案 3 :(得分:0)
这是Geert和Erik提出的想法的一个转折点。我认为这可以最大限度地减少对现有代码的更改。
declare variable $Q-GEO :=
cts:and-query(
($q-geospatial,
(: TODO This smells funny. :)
cts:word-query(
"*",
("case-insensitive", "whitespace-insensitive", "wildcarded",
"diacritic-insensitive")) )) ;
declare variable $Q-FT := cts:query(search:parse($q-text, $options)) ;
search:resolve(
document { cts:and-query(($Q-GEO, $Q-FT)) }/*,
$options,
xs:unsignedLong(xdmp:get-request-field("start", "1")),
(: TODO Rarely a good idea to fetch so many records :)
12000)
我同意之前的评论,word-query *
和12000
需要审核。对我来说,那些看似等待发生的性能问题。