3

我正在使用 MarkLogic 9 开发基于 Web 的搜索应用程序。我有一个查询构建界面,允许用户将字符串输入到与数据库中文档的特定 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)

以下是输入的字符串和返回的查询的一些示例:

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

这个正确地为“大脑”术语的 3 个字段(标题、摘要、网格术语)生成 jsonPropertyWordQuery,但对于其他两个术语没有这样做,它只是生成一个 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 或绑定对象?

任何帮助将不胜感激。

4

2 回答 2

7

It isn't clear to me what you exact query string is.

If the query string is something like "main:(cat OR dog)" then the OR is not a keyword in that context. What is allowed after a tag is pretty limited, and is not the full range of query language, it it just a list of literals.

If the query string is something like "main:cat OR dog then the scope of the tag is just cat.

It isn't unreasonable to want the () after a tag to scope an entire query now you can bind a function to the tag (it made no sense when it was fixed to a range index or field), but that isn't how the grammar is set up.

So you'll just have to do things piecemeal: main:cat OR main:dog

Or: given the set of values passed into your function, space-concatenate them and pass that to a separate call to cts:parse to get them interpreted as a query you can wrap.

于 2017-07-24T22:24:38.567 回答
2

正如 Mary 所解释的,您应该阅读main:cat OR dog(main:cat) OR dog. 您可以执行 Erik 建议的操作,并在解析为 之前重写查询main:cat OR main:dog,或者您可以解析cat OR dog(不带前缀),然后对 cts:query 树进行后处理以扩展 cts:word-query 的出现与三个部分or-query 是你所追求的。使用类型开关的递归函数应该可以解决这个问题。

于 2017-07-25T05:27:07.193 回答