I am working on a web-based search application using MarkLogic 9. I have a query building interface that allows users to enter strings into textboxes that correspond to particular JSON properties of the documents in the db. The idea was that the user could enter the search terms exactly as the cts.parse (I use server side javascript, not XQuery) expects them, so that their searches could be arbitrarily complex and I would not have to deal with parsing the queries myself. However after doing some testing, I have discovered an odd phenomena regarding the use of parentheses in the Boolean logic. Namely, when you include parentheses with a statement like cat and (dog OR bird), cts.parse will mistake the OR for a search term.
I will provide an actual example from my website:
I have constructed a bindings object to bind the queries to the elements of my documents,
var qOpts = ["case-insensitive","punctuation-insensitive","whitespace-insensitive","wildcarded"];
var bindings = {
main: function(operator, values, options){
return(
cts.orQuery([
cts.jsonPropertyWordQuery('title',values,qOpts),
cts.jsonPropertyWordQuery('abstract',values,qOpts),
cts.jsonPropertyWordQuery('meshterms',values,qOpts),
])
);
},
}
My server-side scripts call, for example,
cts.parse('main:'+params.mainQuery,bind)
Here are some examples of the strings entered and the queries returned:
- brain OR heart OR lung
cts.orQuery([cts.jsonPropertyWordQuery("title", "brain", ["case-insensitive","punctuation-insensitive","whitespace-insensitive","wildcarded","lang=en"], 1), cts.jsonPropertyWordQuery("abstract", "brain", ["case-insensitive","punctuation-insensitive","whitespace-insensitive","wildcarded","lang=en"], 1), cts.jsonPropertyWordQuery("meshterms", "brain", ["case-insensitive","punctuation-insensitive","whitespace-insensitive","wildcarded","lang=en"], 1), cts.wordQuery("heart", ["lang=en"], 1), cts.wordQuery("lung", ["lang=en"], 1)], [])
This one properly generates the jsonPropertyWordQuery for the 3 fields (title,abstract, mesh terms) for the "brain" term, but fails to do so for the other two terms, for which it simply generates a cts.wordQuery().
- brain OR heart AND lung
cts.orQuery([cts.jsonPropertyWordQuery("title", "brain", ["case-insensitive","punctuation-insensitive","whitespace-insensitive","wildcarded","lang=en"], 1), cts.jsonPropertyWordQuery("abstract", "brain", ["case-insensitive","punctuation-insensitive","whitespace-insensitive","wildcarded","lang=en"], 1), cts.jsonPropertyWordQuery("meshterms", "brain", ["case-insensitive","punctuation-insensitive","whitespace-insensitive","wildcarded","lang=en"], 1), cts.andQuery([cts.wordQuery("heart", ["lang=en"], 1), cts.wordQuery("lung", ["lang=en"], 1)], ["unordered"])], [])
- brain OR (heart AND lung)
cts.orQuery([cts.jsonPropertyWordQuery("title", "brain", ["case-insensitive","punctuation-insensitive","whitespace-insensitive","wildcarded","lang=en"], 1), cts.jsonPropertyWordQuery("abstract", "brain", ["case-insensitive","punctuation-insensitive","whitespace-insensitive","wildcarded","lang=en"], 1), cts.jsonPropertyWordQuery("meshterms", "brain", ["case-insensitive","punctuation-insensitive","whitespace-insensitive","wildcarded","lang=en"], 1), cts.andQuery([cts.wordQuery("heart", ["lang=en"], 1), cts.wordQuery("lung", ["lang=en"], 1)], ["unordered"])], [])
2 and 3 appear to be the same. The first part correct generates a jsonPropertyWordQuery but the other terms are anded as basic word queries, which I am trying to avoid.
- (brain OR heart) AND lung
cts.andQuery([cts.orQuery([cts.jsonPropertyWordQuery("title", ["brain", "OR", "heart"], ["case-insensitive","punctuation-insensitive","whitespace-insensitive","wildcarded","lang=en"], 1), cts.jsonPropertyWordQuery("abstract", ["brain", "OR", "heart"], ["case-insensitive","punctuation-insensitive","whitespace-insensitive","wildcarded","lang=en"], 1), cts.jsonPropertyWordQuery("meshterms", ["brain", "OR", "heart"], ["case-insensitive","punctuation-insensitive","whitespace-insensitive","wildcarded","lang=en"], 1)], []), cts.wordQuery("lung", ["lang=en"], 1)
Here, the parser does not seem to recognize that OR is an operator because, even though it is correctly generating jsonPropertyWordQueries, it is including OR as a term in the search.
Honestly, I am having trouble finding any query that is correctly, which leads me to believe that I must be doing something wrong. I have no idea where that could be. Am I misusing cts.parse or the bindings object?
Any help would be greatly appreciated.