Alan,

It appears the behavior of search:parse() and cts:parse() are different in this 
respect. cts:parse() uses the individual word tokens in the query, the 
equivalent of an ORing them:

cts:parse('by:(twain frost)', 
  map:new(map:entry("by", cts:element-reference(xs:QName("name")))))

=> cts:element-word-query(fn:QName("","name"), ("twain", "frost"), ("lang=en"), 
1)

While search:parse joins the tokens into a single phrase, as you discovered:

search:parse("by:(twain frost)", 
  <options xmlns="http://marklogic.com/appservices/search";>
    <constraint name="by">
      <word>
        <element ns="http://authors-r-us.com"; name="name"/>
      </word>
    </constraint>
  </options>)

=> <cts:element-word-query xmlns:cts="http://marklogic.com/cts";>
  <cts:element xmlns:_1="http://authors-r-us.com";>_1:name</cts:element>
  <cts:text xml:lang="en">twain frost</cts:text>
</cts:element-word-query>

Since you want an ANDed query, neither of these will solve your problem out of 
the box. As Erik suggested, a custom constraint could handle this. You could 
also use cts:parse() and post-process the output query to convert multi-token 
element-word-queries into multiple ANDed single-token queries.

-Will


> On Feb 27, 2018, at 6:11 PM, Erik Hennum <erik.hen...@marklogic.com> wrote:
> 
> Hi, Alan:
> 
> Please work with your support representative to create a ticket to 
> investigate the issue.
> 
> You might experiment with a custom constraint to see whether that comes 
> closer to what you need.
> 
> Alternatively, you might find that cts:parse() provides a faster solution 
> than search:parse() for parsing query text.
> 
> 
> Hoping that helps,
> 
> 
> Erik Hennum
> 
> 
> 
> ________________________________________
> From: general-boun...@developer.marklogic.com 
> <general-boun...@developer.marklogic.com> on behalf of Alan Darnell 
> <alan.darn...@utoronto.ca>
> Sent: Tuesday, February 27, 2018 3:54:17 PM
> To: General Developer Discussion
> Subject: [MarkLogic Dev General] Field Word Queries using Search API
> 
> We’ve noticed that when using a Field constraint with the Search API, that 
> search strings such as:
> 
> KW:(war peace)
> 
> are parsed in such a way that the two words are treated as a phrase.  The 
> resulting query looks like this:
> 
> (cts:search(/book, cts:field-word-query("keywords", "war peace", 
> ("case-insensitive","diacritic-insensitive","punctuation-insensitive","wildcarded","lang=en"),
>  1), ("score-logtfidf",cts:score-order("descending")), 1))[1 to 10]
> 
> This is different than how a none-constrained search is treated, where the 
> two words are passed to two separate cts:word-query functions, which in turn 
> are AND’d together.
> 
> (cts:search(/book, cts:and-query((cts:word-query("war", 
> ("case-insensitive","diacritic-insensitive","punctuation-insensitive","wildcarded","lang=en"),
>  1), cts:word-query("peace", 
> ("case-insensitive","diacritic-insensitive","punctuation-insensitive","wildcarded","lang=en"),
>  1)), ()), ("score-logtfidf",cts:score-order("descending")), 1))[1 to 10]
> 
> It is also not the same way that non-Field based constraints are handled.  
> For example, we have an element constraint (SE) defined on the element 
> “collection-meta” that produces an AND’d query like this
> 
> (cts:search(/book, cts:element-query(fn:QName("","collection-meta"), 
> cts:and-query((cts:word-query("war", 
> ("case-insensitive","diacritic-insensitive","punctuation-insensitive","wildcarded","lang=en"),
>  1), cts:word-query("peace", 
> ("case-insensitive","diacritic-insensitive","punctuation-insensitive","wildcarded","lang=en"),
>  1)), ()), ()), ("score-logtfidf",cts:score-order("descending")), 1))[1 to 10]
> 
> in response to this input SE:(war peace)
> 
> What we need is a way to produce the following:
> 
> (cts:search(/book, cts:and-query((cts:field-word-query("keywords", "war", 
> ("case-insensitive","diacritic-insensitive","punctuation-insensitive","wildcarded","lang=en"),
>  1), cts:field-word-query("keywords", "peace", 
> ("case-insensitive","diacritic-insensitive","punctuation-insensitive","wildcarded","lang=en"),
>  1)), ()), ("score-logtfidf",cts:score-order("descending")), 1))[1 to 10]
> 
> We can do this by passing this string to search:
> 
> KW:war AND KW:peace
> 
> but that’s not practical from a user perspective.  We’d also like to avoid 
> either editing the Search query module code or having to parse out the user 
> entered string and tokenize for words and prefix each of these with the 
> constraint name. The first doesn’t seem wise and the second seems too much 
> like a hack.
> 
> Question:
> 
> Is there a way to override the default behaviour of Field based constraints 
> in the Search API (using options) so that words passed to the constraint are 
> parsed as individual words and used to construct an AND query in the same way 
> non-Field based constraints and unconstrained searches operate?
> 
> Thanks for any help.
> 
> 
> Alan
> 
> 
> 
> 
> 
> _______________________________________________
> General mailing list
> General@developer.marklogic.com
> Manage your subscription at:
> https://urldefense.proofpoint.com/v2/url?u=http-3A__developer.marklogic.com_mailman_listinfo_general&d=DwIF-g&c=IdrBOxAMwHPzAikPNzltHw&r=_thRNTuzvzYaEDwaA_AfnAe5hN2lWgi6qdluz6ApLYI&m=Gx4VRQy6D_HNB0Fht9JwGN9wlHS9vllD9j0vc6NCRFU&s=XUc3O0EahFcKFMNrzhS6RniwW3J5ElS74ZbZvj-8_TI&e=
> _______________________________________________
> General mailing list
> General@developer.marklogic.com
> Manage your subscription at: 
> https://urldefense.proofpoint.com/v2/url?u=http-3A__developer.marklogic.com_mailman_listinfo_general&d=DwIF-g&c=IdrBOxAMwHPzAikPNzltHw&r=_thRNTuzvzYaEDwaA_AfnAe5hN2lWgi6qdluz6ApLYI&m=Gx4VRQy6D_HNB0Fht9JwGN9wlHS9vllD9j0vc6NCRFU&s=XUc3O0EahFcKFMNrzhS6RniwW3J5ElS74ZbZvj-8_TI&e=

_______________________________________________
General mailing list
General@developer.marklogic.com
Manage your subscription at: 
http://developer.marklogic.com/mailman/listinfo/general

Reply via email to