xquerymarklogiccts-search

Moving where into cts:search


Given this query:

for $d in cts:search(
      fn:doc(),
      cts:and-query(
       (            
         cts:collection-query(('InProgress_Audit'))
       )
      ))          
      where not(fn:contains($d//TitleDate/text(),"Z"))
      return <p>{document-uri($d)}</p>

How do I move the "where" constraint into the CTS search query?


Solution

  • This uses cts:query to apply your constraints:

    for $d in cts:search(
      fn:doc(),
      cts:and-not-query(            
         cts:collection-query('InProgress_Audit'),
         cts:element-query(xs:QName('TitleDate'),
           cts:word-query('*Z*', 'wildcarded'))
      ))
    return <p>{document-uri($d)}</p>
    

    There are index options to speed up wildcarded searches. You could also use a range index on TitleDate in combination with a cts:element-range-index-query to speed this up even further.

    Update: As @mblakele points out in the comments, cts:element-value-query may be faster than the nested cts:element-query/cts:word-query:

    cts:element-value-query(xs:QName('TitleDate'), '*Z*', 'wildcarded')
    

    And using cts:uris will be faster than making many repeated calls to document-uri(). However, you would need to enable the URI lexicon option in your settings. Putting all that together, the query would look like:

    cts:uris((), 'document',
      cts:and-not-query((            
         cts:collection-query('InProgress_Audit'),
         cts:element-value-query(xs:QName('TitleDate'), 
           '*Z*', 'wildcarded')
      ))) ! element p { . }