Hi Christian,
I refactored my xquery and it's now running very smooth, faster than ever. Thanks a lot for your great help. I also followed your advice, creating a new index just for the full-text-search in mixed-content-environments. This approach is solving a lot of problems I had in the past... Thanks again.
I want to use also your programmatic way to specify full-text options only once in the query, cause it would make my code much cleaner:
let $ft := map { 'wildcards': true() } let $terms := 'pa.*' for $city in ft:search('factbook', $terms, $ft)/parent::name[ancestor::city] let $hits := ft:mark($city[ft:contains(text(), $terms, $ft)]) return let $name := $city/ancestor::country/name return ($hits, $name)
The $options argument in ft:search has most the full-text options, I need. The only problem left is, to integrate the full-text options 'case sensitive' and 'diacritics sensitive'. Is there any way, to get those options inside the ft:search function?
Günter
Am 05.01.2016 um 19:56 schrieb Christian Grün christian.gruen@gmail.com:
Hi Günter,
I had one more look at the slow query you were encountering:
for $city in doc('factbook')//city/name for $hits in ft:mark($city[.//text() contains text {$query} using wildcards]) let $country_of_city := $city/ancestor::country/name return (: slow version: Evaluating 35.78 :) (: <hit><city>{$hits}</city><country>{$country_of_city}</country></hit> :)
This one was more tricky than I expected, because the ft:mark function can produce multiple results for a single node. This is why the sliding of the let clause, which slows down your query, can be beneficial in other cases. The following query will generate 20 results (10 "mark" elements, 10 text nodes), so it will be evaluated faster if the let clause is slided over the for clause:
let $input := (<X>{ 'A.A.A.A.A.A.A.A.A.A.' }</X> update () )/text() for $hits in ft:mark($input[. contains text 'A']) let $parent := $input/.. return <hit id='{ db:node-id($parent) }'>{ $hits }</hit>
Well, those are lots of internal details that I think you can easily ignore. In a nutshell: Just use 'let' and 'where' instead tof 'for':
let $input := (<X>{ 'A.A.A.A.A.A.A.A.A.A.' }</X> update () )/text() let $hits := ft:mark($input[. contains text 'A']) where $hits let $parent := $input/.. return <hit id='{ db:node-id($parent) }'>{ $hits }</hit>
Christian