I had to add geo-spatial search capability to an already existing app which uses search:search API and has full text search and faceted search. I've read about Extending the Search API, but I just don't have the time right now. So, I thought I will adapt my code in order to just do an intersection of the two result sets (one returned by the search:search API and the other returned by the cts:search
that allows cts:polygon
search). Unfortunately the intersection degrades heavily the execution time.
Is there a better way to optimize or speed up the following expression bellow?
$results_fts//search:result[./search:metadata/Vhe eq $geo_results//root/Vhe]
Here is my code:
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;
As a footnote to Dave's good advice, another alternative would be to use search:parse() instead of search:search() to convert the second search request to a cts:query before running the cts:search().
http://docs.marklogic.com/search:parse?q=search:parse&v=8.0&api=true
Then, add the cts:query() generated search:parse() to the list of subqueries within the existing cts:and-query() and run a single search.
It's not clear to me what the cts:word-query("*") clause within the geospatial query is doing, but that's unrelated to the main point.