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 <[email protected]> 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: [email protected]
> <[email protected]> on behalf of Alan Darnell
> <[email protected]>
> 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
> [email protected]
> 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
> [email protected]
> 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
[email protected]
Manage your subscription at:
http://developer.marklogic.com/mailman/listinfo/general