Search code examples
marklogicmarklogic-9

Marklogic Search Grammar syntax with constraints


I have constraints like below.. with a constraint

<options xmlns="http://marklogic.com/appservices/search">
    <additional-query>
        <cts:and-query xmlns:cts="http://marklogic.com/cts">
            <cts:collection-query>
                <cts:uri>OncoWatch</cts:uri>
            </cts:collection-query>
        </cts:and-query>
    </additional-query>
    <constraint name="search-text">
        <word>
            <field name="wos_topic"/>
        </word>
    </constraint>
    <term>
        <term-option>case-insensitive</term-option>
        <term-option>punctuation-insensitive</term-option>
        <term-option>whitespace-insensitive</term-option>
        <term-option>wildcarded</term-option>
    </term>
</options>

When I do the search string '(search-text:(patient* OR adult*))' I get results completely different from when I do this '(search-text:patient*) OR (search-text:adult*)'.. Isn't both the same ?


Solution

  • You can easily see the difference if you apply search:parse on your search strings:

    xquery version "1.0-ml";
    
    import module namespace search = "http://marklogic.com/appservices/search"
         at "/MarkLogic/appservices/search/search.xqy";
    
    let $options := <options xmlns="http://marklogic.com/appservices/search">
        <additional-query>
            <cts:and-query xmlns:cts="http://marklogic.com/cts">
                <cts:collection-query>
                    <cts:uri>OncoWatch</cts:uri>
                </cts:collection-query>
            </cts:and-query>
        </additional-query>
        <constraint name="search-text">
            <word>
                <field name="wos_topic"/>
            </word>
        </constraint>
        <term>
            <term-option>case-insensitive</term-option>
            <term-option>punctuation-insensitive</term-option>
            <term-option>whitespace-insensitive</term-option>
            <term-option>wildcarded</term-option>
        </term>
    </options>
    return (
      search:parse("(search-text:(patient* OR adult*))", $options),
      search:parse("(search-text:patient*) OR (search-text:adult*)", $options)
    )
    

    The search parser supports fairly complex search strings with AND, OR, NEAR, etc, but the support for feeding multiple values into a single constraint is lacking. The latter is the right way of writing it. The first simply gets the parser confused from the looks of it, and as a result the OR gets lost, effectively causing it to search for the phrase search-text:"patient* adult*" which is kind of the same as requiring both terms.

    HTH!