Search code examples
xquerymarklogic

Get intersection with element range index


How I can get the intersection between an existing element range index and a sequence of words in an optimized way?

My point here focuses on memory optimization, I know that I can fetch the data using cts:element-values and use map objects to do the job. But why I should that if there is a query that do this intersection with the cached range index directly.

ex:

Range Index (test1, test2, test3) / Sequence (test1, test4, test5)

query result = test1

Knowing that this range index created for a word list exists in one document. I'm try to avoid put them in a separate documents, as well as avoid using fragmentation.


Solution

  • I believe this will do the trick for you:

    let $myIndex := "myIndex"
    
    let $sequence := ("one", "two two", "three")
    
    let $or-query := cts:or-query(($sequence ! cts:word-query(.)))
    
    return
      cts:element-values(xs:QName($myIndex),(),(), cts:element-query(xs:QName($myIndex), $or-query ))
    

    Per your comment below, it's a bit of a hack but I was able to achieve what I believe is the desired result with this:

    fn:distinct-values(
      cts:search(//lastname, 
          cts:or-query(($sequence ! 
             cts:element-query(xs:QName("lastname"), 
                cts:element-value-query(xs:QName("lastname"), ., "self")
             )
          ))
      )/string()
    )
    

    Just change the XPath at the beginning to be your desired element as well as the QName in element-query. Whether or not thats faster than element-values and checking each of the values in a map I couldn't tell you.

    A third approach you could try, if these values are really only in a single document exclusively for storing them, would be to change the databases fragmentation strategy. Then my approach #1 should work. [Obligatory disclaimer about unintended consequences that could ensue from this]