Hi Christian,
Thank you very much for your comments on this. I ended up doing this:
ft:mark(ft:search("edil-new", "fas", map {"wildcards":"true"})/ancestor::entry)
which gives me everything that I was expecting and is performant as expected. Basically, I took this:
for $x in db:get('edil-new')/sample/entry return $x[descendant::text() contains text {'fas'}]
then looked at the Optimised Query in the GUI and replicated that and translated the "using wildcards" into the map from the documentation.
Writing query optimizers is very hard. I have never tried my hand at it but writing them is an art and a science from what I have read.
Thanks and all the best, Chris
On Wed, Oct 05, 2022 at 03:25:31PM +0200, Christian Grün wrote:
Hi Chris,
for $x in db:get($db)/sample/entry return ft:mark($x[descendant::text() contains text {'fas'} using wildcards])
which ran in 2528.78ms and return 170 results. This seemed rather slow so I started to work on it. I also ran this:
for $x in db:get($db)/sample/entry return $x[descendant::text() contains text {'fas'} using wildcards]
which ran in 57.77ms and returned 35 results. I was very suprised by this as I had expected it to run in the same time and return the same result set.
It’s tricky for the optimizer to rewrite the first expression in a way which both finds results in the index and marks the results. One common (albeit not obvious) solution is to define a search function and call it twice:
let $test := function($node) { $node/descendant::text() contains text { $fas } using wildcards } for $entry in db:get($db)/sample/entry[$test(.)] return ft:mark($entry[$test(.)])
The query optimizer will inline the code and can then rewrite it for index access.
ft:mark(db:get('edil-new')/sample/entry[descendant::text() contains text 'fas' using wildcards])
I do not see the full-text index being applied and it takes 2283.14 ms (much like I had seen before).
My assumption would be that edil-new contains no full-text index (?).
Best, Christian