MarkLogic 9 cts.parse неправильно анализирует запросы
Я работаю над поисковым веб-приложением, использующим MarkLogic 9. У меня есть интерфейс построения запросов, который позволяет пользователям вводить строки в текстовые поля, которые соответствуют определенным свойствам JSON документов в БД. Идея заключалась в том, что пользователь мог вводить условия поиска в точности так, как их ожидает cts.parse (я использую javascript на стороне сервера, а не XQuery), поэтому их поиск может быть сколь угодно сложным, и мне не придется самостоятельно разбирать запросы., Однако после некоторого тестирования я обнаружил странное явление, касающееся использования скобок в булевой логике. А именно, когда вы включаете круглые скобки с такими утверждениями, как cat и (dog OR bird), cts.parse будет ошибочно принимать OR за поисковый запрос.
Я приведу пример с моего сайта:
Я создал объект привязки, чтобы связать запросы с элементами моих документов,
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),
])
);
},
}
Мои серверные скрипты вызывают, например,
cts.parse('main:'+params.mainQuery,bind)
Вот несколько примеров введенных строк и возвращенных запросов:
- мозг или сердце или легкое
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)], [])
Он правильно генерирует jsonPropertyWordQuery для 3 полей (заголовок, аннотация, термины сетки) для термина "мозг", но не делает этого для двух других терминов, для которых он просто генерирует cts.wordQuery().
- мозг или сердце и легкое
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"])], [])
- мозг или (сердце и легкие)
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 и 3 выглядят одинаково. Первая правильная часть генерирует jsonPropertyWordQuery, но другие термины добавляются в виде базовых запросов к словам, которых я пытаюсь избежать.
- (мозг или сердце) и легкие
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)
Здесь парсер, похоже, не распознает, что OR является оператором, потому что, хотя он правильно генерирует jsonPropertyWordQueries, он включает OR в качестве термина в поиске.
Честно говоря, у меня возникают проблемы с поиском правильного запроса, что приводит меня к мысли, что я, должно быть, делаю что-то не так. Я понятия не имею, где это может быть. Я неправильно использую cts.parse или объект bindings?
Любая помощь будет принята с благодарностью.
2 ответа
Мне не ясно, какая у вас точная строка запроса.
Если строка запроса что-то вроде "main:(cat OR dog)"
тогда OR не является ключевым словом в этом контексте. То, что разрешено после тега, довольно ограничено, и это не полный диапазон языка запросов, это просто список литералов.
Если строка запроса что-то вроде "main:cat OR dog
тогда область применения тега cat
,
Желательно, чтобы () после тега охватывал весь запрос, теперь вы можете привязать функцию к тегу (это не имело смысла, когда она была зафиксирована в индексе диапазона или поле), но это не так грамматика настроена.
Так что вам просто нужно делать что-то по частям: main:cat OR main:dog
Или: учитывая набор значений, переданных в вашу функцию, соедините их пробелами и передайте их отдельному вызову cts:parse
чтобы получить их интерпретировать как запрос, который вы можете обернуть.
Как также объясняет Мария, вы должны прочитать main:cat OR dog
как (main:cat) OR dog
, Вы можете сделать что-то, как предлагает Эрик, и переписать запрос, прежде чем анализировать main:cat OR main:dog
или вы могли бы разобрать cat OR dog
(без префикса), а затем постобработать дерево запросов cts: для расширения вхождений cts:word-query с тремя или несколькими запросами, которые вы ищете. Рекурсивная функция, использующая переключатель типов, должна добиться цели.
НТН!