Cloudant - 使用存储为文本的数字进行 Lucene 范围搜索

Cloudant - Lucene range search using numbers stored as text

我在 Cloudant 中有许多文档,它们具有字符串类型的 ID 字段。 ID 可以是简单的字符串,如 "aaa"、"bbb" 或存储为文本的数字,例如“111”,“222”等。我需要能够使用上面的字段进行全文搜索,但是我遇到了一些问题。

假设我有两个文档,ID="aaa" 和 ID="111",然后使用查询进行搜索:

return第一个文档,如预期

return没什么,但是

return第二个文件,所以至少有办法找回它。

不幸的是,在搜索范围时:

我没有得到任何结果,而且我不知道该怎么做才能解决这个问题。这种情况有什么特殊的语法吗?

更新:

索引函数:

function(doc){
  if(!doc.ID) return;
  index("ID", doc.ID, { index:'not_analyzed_no_norms', store:true });
}

将索引更改为 analyzed 没有帮助。分析器本身是关键字,但更改为标准也无济于事。

更新 2

只是为了添加更多上下文,因为我想我错过了一个关键点。我索引的字段将使用范围进行搜索,最小值和最大值都可以由用户提供。因此,其中一个可能是存储为字符串的数字,而另一个是标准的非数字文本。例如搜索 ID >= "11" 且 ID <= "foo".

的所有文档

假设数据库包含 ID 为“1”、“5”、"alpha"、"beta"、"gamma" 的文档,此查询应 return“5”, "alpha"、"beta"。请注意,“5”实际上应该是 returned,因为字符串“5”大于字符串“11”。

您可以像这样 return 获取这两个文档:

q=ID:["111" TO "CCC"]

这是一个实际的工作示例:

https://rajsingh.cloudant.com/facetrangetest/_design/ddoc/_search/f?q=ID:[%22111%22%20TO%20%22CCC%22]

我发现了一些奇怪的东西。似乎仅当至少一个范围值是字符串时,对字符串的范围查询才有效。查询 ID:["111" TO "555"] 也不会 return 任何东西,所以这可能以某种方式解析为数字查询?可能是一个错误。

首先,我建议使用关键字分析器,这样您就可以在索引和搜索过程中控制正确的分词。

"analyzer": "keyword",
"index": "function(doc){\n  if(!doc.ID) return;\n  index(\"ID\", doc.ID, {store:true });\n}

要检索 _id 为“111”的文档,请使用以下范围查询:

curl -X GET "http://.../facetrangetest/_design/ddoc/_search/f?q=ID:\[111%20TO%A\]" 

如果您使用查询 q=ID:\[111%20TO%20999\],Cloudant 搜索在两个范围大小上看到的数字,会将其解释为 NumericRangeQuery;由于您的“111”ID 是一个字符串,因此它不会成为返回结果的一部分。在查询 [111%20TO%20A] 中包含一个字符串将使 Cloudant 将其解释为对字符串的范围查询。

我们的团队刚刚找到了解决方法。我们设法通过添加一些任意字符来获得正确的结果,例如'a' 到范围上限值,并通过引入额外的搜索词,以排除 ID 介于范围上限值和范围上限值 + 'a'.

之间的文档

搜索范围时

ID:[X 到 Y]

实际查询是

(ID:[X TO Ya] AND -ID:{Y TO Ya])

例如,要查找 ID 介于 23 和 758 之间的文档,我们执行

(ID:[23 TO 758a] AND -ID:{758 TO 758a]).

这也可以在查询中使用正则表达式来实现。这条线:

curl -X POST "https://.../facetrangetest/_design/ddoc/_search/f" -d '{"q":"ID:/<23-758>/"}' | jq .

这个正则表达式的意思是检索ID字段从23到758的所有文档。斜线:/ /用于括起正则表达式;间隔包含在 <>.