Cloudant - 使用存储为文本的数字进行 Lucene 范围搜索
Cloudant - Lucene range search using numbers stored as text
我在 Cloudant 中有许多文档,它们具有字符串类型的 ID 字段。 ID 可以是简单的字符串,如 "aaa"、"bbb" 或存储为文本的数字,例如“111”,“222”等。我需要能够使用上面的字段进行全文搜索,但是我遇到了一些问题。
假设我有两个文档,ID="aaa" 和 ID="111",然后使用查询进行搜索:
- ID:aaa
- ID:"aaa"
- ID:[aaa TO zzz]
- ID:["aaa" 至 "zzz"]
return第一个文档,如预期
- ID:111
return没什么,但是
- ID:"111"
return第二个文件,所以至少有办法找回它。
不幸的是,在搜索范围时:
- 编号:[111至999]
- ID:["111" 到 "999"]
我没有得到任何结果,而且我不知道该怎么做才能解决这个问题。这种情况有什么特殊的语法吗?
更新:
索引函数:
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"]
这是一个实际的工作示例:
我发现了一些奇怪的东西。似乎仅当至少一个范围值是字符串时,对字符串的范围查询才有效。查询 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的所有文档。斜线:/
/
用于括起正则表达式;间隔包含在 <>
.
内
我在 Cloudant 中有许多文档,它们具有字符串类型的 ID 字段。 ID 可以是简单的字符串,如 "aaa"、"bbb" 或存储为文本的数字,例如“111”,“222”等。我需要能够使用上面的字段进行全文搜索,但是我遇到了一些问题。
假设我有两个文档,ID="aaa" 和 ID="111",然后使用查询进行搜索:
- ID:aaa
- ID:"aaa"
- ID:[aaa TO zzz]
- ID:["aaa" 至 "zzz"]
return第一个文档,如预期
- ID:111
return没什么,但是
- ID:"111"
return第二个文件,所以至少有办法找回它。
不幸的是,在搜索范围时:
- 编号:[111至999]
- ID:["111" 到 "999"]
我没有得到任何结果,而且我不知道该怎么做才能解决这个问题。这种情况有什么特殊的语法吗?
更新:
索引函数:
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"]
这是一个实际的工作示例:
我发现了一些奇怪的东西。似乎仅当至少一个范围值是字符串时,对字符串的范围查询才有效。查询 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的所有文档。斜线:/
/
用于括起正则表达式;间隔包含在 <>
.