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