elasticsearch - 弹性搜索:一旦我们得到想要的结果,如何终止多搜索查询
问题描述
我们有一个带有名为“Type”的字符串字段的弹性搜索文档。该字段可以具有从“A”到“Z”的不同值。多个文档可以具有相同的类型,即多个文档可以具有类型“A”
我们想编写一个弹性搜索查询,最多返回 30 个这样的文档。我们希望输出根据类型在不同的组中。例如:
- 如果我们有 10 个 A 类型的文档,15 个 B 类型的文档,20 个 C 类型的文档,我应该得到所有 10 个类型 A,所有 15 个类型 B 和 5 个类型 C。
- 如果我们有 0 个 A 类文档,10 个 B 类文档,15 个 C 类文档,20 个 D 类文档,我应该得到所有 10 个 B 类文档,15 个 C 类文档和 5 个 D 类文档。
- 最坏的情况:如果我们没有任何 A ... Y 类型的文档和 30 个 Z 类型的文档,我应该得到 30 个 Z 类型的文档。
我为此编写了一个非常基本的多搜索查询(总共 26 个查询),即
POST _msearch/
{"index":"<index_name>","type":"<type>"}
{"from":0,"size":30,"query":{"bool":{"must":[{"terms":{"type":["A"]}}]}}}
{"index":"<index_name>","type":"<type>"}
{"from":0,"size":30,"query":{"bool":{"must":[{"terms":{"type":["B"]}}]}}}
...
{"index":"<index_name>","type":"<type>"}
{"from":0,"size":30,"query":{"bool":{"must":[{"terms":{"type":["Z"]}}]}}}
我担心多搜索查询的执行,即案例 1 和案例 2,我们从前几个查询中得到了足够的输出,即 30 个文档,那么我们为什么要执行其余的多搜索查询呢?一旦我们获得所需数量的结果,是否有任何方法可以停止多搜索查询操作,即一旦我们获得 30 个或更多结果就终止多搜索。
请注意:
- 我在这里给出了非常简单的条件,即不同的多重搜索的条件比仅仅基于类型更复杂。
- 我们希望输出中有多个集合,即类型 A、类型 B 等,都在不同的集合中。(由于这个限制,我们不得不排除无痛脚本选项)
解决方案
看起来您可以通过使用size
和 a进行一次搜索来实现您想要的结果sort
,还可以选择使用bool
将查询组合为一个。
我可以提前终止多搜索查询吗?
不,从Multi Search的文档中我们可以得出结论。它执行多个搜索请求,具有一定的并发性,只有在所有查询完成后才发回结果。
它很像Bulk API,一种轻松执行并行请求的方法。
我可以按照自定义的顺序获取匹配的文档吗?
是的,这就是sort
目的。为了实现原始帖子中描述的行为,使用这个调用就足够了:
POST /<index_name>/<index_type>/_search?sort=type:asc&size=30
我可以对多个索引发出一个搜索请求并仍然使用sort
吗?
是的,您只需要定义索引列表:
POST /multisearch1,mutlisearch2/<index_type>/_search?sort=type:asc&size=30
或通配符表达式:
POST /multisearch*/<index_type>/_search?sort=type:asc&size=30
我可以按任意顺序排序吗?
是的,例如使用基于脚本的排序。例如,如果您希望按type
以下顺序查看结果:X
, C
, A
,您可以编写如下脚本:
POST /<index_name>/<type>/_search
{
"size": 30,
"sort": {
"_script": {
"type": "number",
"script": {
"lang": "painless",
"source": """
int r = 1;
if(doc['type'].value == 'X') {
r = 100;
} else if(doc['type'].value == 'C') {
r = 10;
} else if(doc['type'].value == 'A') {
r = 5;
}
r;
"""
},
"order": "desc"
}
}
}
这也适用于多个集合(如上面的查询)。
如果我有一个取决于 值的复杂查询,我可以这样做type
吗?
是的,没问题,bool
例如使用查询:
POST /<index_name>/<type>/_search
{
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"term": {
"type": "A"
}
},
{
"match": {
"description": "Quick fox"
}
}
]
}
},
{
"bool": {
"must": [
{
"term": {
"type": "X"
}
},
{
"match": {
"description": "Quick bear"
}
}
]
}
}
]
}
},
"size": 30,
"sort": {
"_script": {
"type": "number",
"script": {
"lang": "painless",
"source": """
int r = 1;
if(doc['type'].value == 'X') {
r = 100;
} else if(doc['type'].value == 'C') {
r = 10;
} else if(doc['type'].value == 'A') {
r = 5;
}
r;
"""
},
"order": "desc"
}
}
}
希望有帮助!
推荐阅读
- windows-10 - Windows 10:仅将窗口固定到特定任务栏
- google-apps-script - 需要谷歌电子表格脚本错误权限
- javascript - 在反应中使用 =, =>, : 有什么不同?
- c# - 预览 OpenXML 创建的 zip 文件中的文档时出错
- javascript - 如何在javascript中获取元素的背景div
- python - Python:float() 参数必须是字符串或数字,而不是“期间”
- python - 什么是 numpy.core._multiarray_umath.implement_array_function 以及为什么要花费大量时间?
- r - 需要帮助将列数据组织和汇总到 R Markdown
- javascript - 根据请求jQuery将pdf从后端传输到前端
- java - 如何使用 selenium4 获取 .har 文件或网络请求