MarkLogic 9 cts.parse неправильно анализирует запросы

Я работаю над поисковым веб-приложением с использованием MarkLogic 9. У меня есть интерфейс построения запросов, который позволяет пользователям вводить строки в текстовые поля, соответствующие определенным свойствам JSON документов в базе данных. Идея заключалась в том, что пользователь мог вводить условия поиска точно так, как их ожидает cts.parse (я использую javascript на стороне сервера, а не XQuery), чтобы их поиск мог быть сколь угодно сложным, и мне не пришлось бы заниматься синтаксическим анализом запросов самостоятельно. . Однако после некоторого тестирования я обнаружил странный феномен, связанный с использованием круглых скобок в булевой логике. А именно, когда вы включаете круглые скобки в такие утверждения, как кошка и (собака ИЛИ птица), cts.parse ошибочно принимает ИЛИ за поисковый запрос.

Приведу реальный пример со своего сайта:

Я создал объект привязки для привязки запросов к элементам моих документов,

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)

Вот несколько примеров введенных строк и возвращенных запросов:

  1. мозг ИЛИ сердце ИЛИ легкое

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 ().

  1. мозг ИЛИ сердце И легкие

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"])], [])

  1. мозг ИЛИ (сердце И легкие)

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, но другие термины добавляются как базовые запросы слов, которых я стараюсь избегать.

  1. (мозг ИЛИ сердце) И легкое

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 или объект привязки?

Любая помощь будет принята с благодарностью.


person Alec Daling    schedule 24.07.2017    source источник


Ответы (2)


Мне неясно, какая у вас точная строка запроса.

Если строка запроса похожа на "main:(cat OR dog)", то OR не является ключевым словом в этом контексте. То, что разрешено после тега, довольно ограничено и не является полным диапазоном языка запросов, это просто список литералов.

Если строка запроса имеет вид "main:cat OR dog, тогда область действия тега равна cat.

Нет смысла хотеть, чтобы () после тега охватывала весь запрос, теперь вы можете привязать функцию к тегу (это не имело смысла, когда она была привязана к индексу диапазона или полю), но это не так грамматика настроена.

Так что вам придется делать все по частям: main:cat OR main:dog

Или: учитывая набор значений, переданных в вашу функцию, объедините их пробелом и передайте в отдельный вызов cts:parse, чтобы они интерпретировались как запрос, который вы можете обернуть.

person mholstege    schedule 24.07.2017
comment
Сноска (из моего замененного ответа) - см. docs.marklogic.com/guide / search-dev / cts_query # id_15151 и рассмотрим что-нибудь вроде: const newText = queryText.trim (). split (/ \ s + /). map (term = ›{const result = term.match ( / ^ (И | ИЛИ) $ /)? Term: 'main:' + term; return result;}). Join (''); - person ehennum; 25.07.2017

Как также объяснила Мэри, вы должны читать main:cat OR dog как (main:cat) OR dog. Вы можете сделать что-то вроде того, что предлагает Эрик, и переписать запрос перед синтаксическим анализом до main:cat OR main:dog, или вы можете проанализировать cat OR dog (без префикса), а затем обработать дерево запросов cts: для расширения вхождений cts: word-query с тремя -какое-то или-то, что вам нужно. Рекурсивная функция, использующая машинный переключатель, должна помочь в этом.

HTH!

person grtjn    schedule 25.07.2017
comment
Отлично спасибо. Я думаю, что комбинация ответов охватит все нужные мне варианты использования. Я даже не рассматривал постобработку дерева запросов. - person Alec Daling; 11.08.2017