目录
Bool 查询
Dis_max 查询
Function_score 查询
Nested 查询
Geospatial 查询
1. Geo Point 查询
2. Geo Shape 查询
Elasticsearch(简称为ES)是一个基于Lucene的分布式搜索和分析引擎,它提供了丰富的查询语言和API,可以用于构建高性能、可扩展的全文搜索、日志分析和数据可视化等应用。
在 Elasticsearch 中,复合查询是一种将多个查询组合起来进行检索的方式,可以根据用户的需求进行灵活的组合和定制,常见的复合查询包括 bool、dis_max、function_score 等。以下是一些常见的 ES 复合查询:
1. Bool 查询
bool 查询是 ES 中使用最为广泛的复合查询,可以组合多个查询条件和过滤器,支持must、should、must_not 等子句,可以实现AND、OR、NOT 等逻辑关系操作。
2. Dis_max 查询
dis_max 查询是一种多字段查询,可以在多个字段中搜索相同的关键字,并对得分较高的结果进行返回。它适用于搜索关键字在多个字段中都可能出现的情况。
3. Function_score 查询
function_score 查询可以通过自定义的函数计算得分,可以根据业务需求进行加权排序、过滤、封顶等操作。
4. Nested 查询
nested 查询可以在文档的嵌套对象中进行搜索,适用于包含多个内部对象的文档结构。
5. Geospatial 查询
geospatial 查询可以在 ES 中进行地理位置检索,可以对符合条件的位置信息进行查询和过滤,支持圆形、多边形、距离等多种方式。
总之,ES提供了丰富的查询语言和API,用户可以根据实际的业务需求进行灵活的组合和定制,以实现高效、准确的全文搜索和数据分析。
bool 查询是 Elasticsearch 中一个非常灵活的查询方式,可以根据多个子查询的组合来实现复杂的查询需求。其语法如下:
{
"query": {
"bool": {
"must": [ { ... }, { ... } ],
"should": [ { ... }, { ... } ],
"must_not":[ { ... }, { ... } ],
"filter": { ... }
}
}
}
其中,must 表示“与”关系,所有子查询必须都匹配;而 should 表示“或”关系,只要有一个子查询匹配即可;must_not 表示“非”关系,即要排除掉所有符合条件的文档;filter 则表示对文档进行筛选,不参与计算得分,只保留满足条件的文档。你可以同时使用多个 must、should 或 must_not 子句,以及任意数量的 filter 子句。
下面是一个使用 `bool` 查询的示例 DSL:
{
"query": {
"bool": {
"must": [
{ "match": { "title": "开发" } },
{ "range": { "views": { "gte": 1000 } } }
],
"should": [
{ "match": { "content": "工程师" } },
{ "match": { "content": "编程" } }
],
"must_not": [
{ "match": { "author": "张三" } }
],
"filter": {
"term": { "category": "科技" }
}
}
}
}
这个查询中包含了多个子句,它们的含义如下:
- `must`: 要求文档的 `title` 字段包含“开发”,同时 `views` 字段的值大于等于 1000。
- `should`: 要求文档的 `content` 字段包含“工程师”或“编程”。由于使用了 `should`,因此只要其中一个子句匹配成功,就会增加文档的得分。
- `must_not`: 要求文档的 `author` 字段不为“张三”。由于使用了 `must_not`,因此所有满足该条件的文档得分都会被赋值为 0。
- `filter`: 要求文档的 `category` 字段为“科技”。由于使用了 `filter`,因此只有满足该条件的文档才会被保留。需要注意的是,筛选条件并不参与计算文档得分。通过组合多个 `must`、`should`、`must_not` 和 `filter` 子句,你可以实现非常复杂和灵活的查询逻辑。
Dis_max 查询是 Elasticsearch 中一种用于多个查询子句的组合查询方式。
它会同时执行多个查询,并将每个查询的分值进行比较,取最高分值作为文档的最终分值。Dis_max 查询的语法如下:
{
"query": {
"dis_max": {
"queries": [
{ "match": { "title": "开发" }},
{ "match": { "content": "开发" }}
],
"tie_breaker": 0.3
}
}
}
其中,
queries
字段包含了多个查询子句,以数组的形式列出。在上面的例子中,我们使用了两个match
查询子句,分别匹配title
和content
字段中包含“开发”的文档。当有多个查询子句时,Dis_max 查询会返回所有查询的结果并进行分值计算,选取分值最高的文档。tie_breaker
字段是可选参数,其取值为一个介于 0 到 1 之间的浮点数,代表除了分值以外的因素影响程度。当多个查询子句得分相等时,使用该参数指定的权重进行打分。
function_score
查询是 Elasticsearch 中用于加权得分的一种查询方式,它可以根据指定的公式来计算每个文档的得分,并据此对搜索结果进行排序。下面是一个function_score
查询的示例 DSL
{
"query": {
"function_score": {
"query": {
"match": {
"title": "开发"
}
},
"script_score": {
"script": {
"source": "_score * pow(doc['views'].value, 0.5)"
}
},
"boost_mode": "replace"
}
}
}
这个查询首先使用了一个
match
查询来搜索包含“开发”子串的文档。然后,使用script_score
参数来定义一个脚本,它将搜索得分和views
字段(即文档的浏览次数)的平方根相乘作为最终得分。在这个例子中,我们使用了pow
函数来计算平方根,但你也可以选择使用其他函数来自定义计算方式。最后,使用boost_mode
参数来指定是否替换默认得分(即只使用脚本得分)。需要注意的是,由于脚本计算时会访问文档的字段,所以需要在安全配置下的 Elasticsearch 环境中使用
function_score
查询。除此之外,在高负载系统上运行function_score
查询可能会影响性能,因此要谨慎使用。
nested
查询是 Elasticsearch 中一种常用的嵌套查询方式,可以对嵌套类型的字段进行查询。它可以先匹配文档的主字段,然后再进入嵌套字段中进行查询,最后将匹配的结果合并返回。下面是一个使用
nested
查询的示例 DSL:
{
"query": {
"nested": {
"path": "authors",
"query": {
"bool": {
"must": [
{ "match": { "authors.name": "张三" } },
{ "range": { "authors.age": { "gte": 30 } } }
]
}
}
}
}
}
这个查询中,我们要求查询名为“authors”的嵌套字段,路径为“authors”。其中,“authors”字段在映射中需要被定义为
nested
类型。然后,我们使用bool
查询来对嵌套字段进行进一步的查询,要求name
字段匹配“张三”,并且age
字段的值大于等于 30。需要注意的是,在使用嵌套查询时,必须先定义nested
类型的映射,并且索引数据时也必须按照nested
类型的格式进行索引。否则,嵌套查询可能会返回空结果或错误结果。此外,嵌套查询也有一些限制和性能问题。由于嵌套查询需要创建虚拟文档来存储嵌套对象,因此在查询时会增加内存和 CPU 的开销,尤其是在大数据集上。如果你的数据结构比较复杂,并且需要频繁使用嵌套查询,可能需要重新考虑你的数据模型。
Geospatial 查询是 Elasticsearch 中一种常用的地理位置查询方式,可以根据地理坐标或地理围栏来查询附近的文档。Elasticsearch 支持两种类型的地理位置查询:
- `geo_point`:表示一个具体的地理坐标点,由经度和纬度组成。
- `geo_shape`:表示一个地理围栏,可以是圆形、矩形、多边形、线等形状。下面分别介绍这两种类型的地理位置查询。
使用 `geo_point` 类型的字段,你可以通过 `geo_distance` 查询或 `geo_bounding_box` 查询来查找距离某个地理点一定距离内的文档。
`geo_distance` 查询可以根据给定的经纬度和距离参数来搜索距离该点一定范围内的文档。下面是一个示例 DSL:
{
"query": {
"bool": {
"must": [
{ "match_all": {} }
],
"filter": {
"geo_distance": {
"distance": "10km",
"location": {
"lat": 40.715,
"lon": -74.011
}
}
}
}
}
}
这个查询中,我们要求查询名为“location”的地理坐标字段,距离给定的经纬度 (40.715, -74.011) 不超过 10 公里。需要注意的是,因为这里使用了 `filter` 子句,所以不会对匹配结果进行打分,只会返回符合条件的文档。如果你还想要有打分的效果,可以将 `filter` 改为 `must`。
`geo_bounding_box` 查询则可以在一个矩形范围内搜索文档。下面是一个示例 DSL:
{
"query": {
"bool": {
"must": [
{ "match_all": {} }
],
"filter": {
"geo_bounding_box": {
"location": {
"top_left": {
"lat": 40.73,
"lon": -74.1
},
"bottom_right": {
"lat": 40.01,
"lon": -71.12
}
}
}
}
}
}
}
这个查询中,我们要求查询名为“location”的地理坐标字段,在一个矩形区域内搜索文档。该矩形由左上角 (40.73, -74.1) 和右下角 (40.01, -71.12) 两个点确定。
使用 `geo_shape` 类型的字段,你可以创建各种形状的地理围栏,包括圆、矩形、多边形、线等。然后可以使用 `geo_shape` 查询来查找与这些围栏相交或包含的文档。
下面是一个示例 DSL,使用 `geo_shape` 查询查找与给定多边形相交的文档:
{
"query": {
"bool": {
"must": [
{ "match_all": {} }
],
"filter": {
"geo_shape": {
"location": {
"shape": {
"type": "polygon",
"coordinates": [
[ [ -70.5, 41 ], [ -68.5, 41 ], [ -69.5, 39 ] ]
]
}
}
}
}
}
}
}
这个查询中,我们要求查询名为“location”的地理围栏字段,查找与给定多边形相交的文档。需要注意的是,这里的多边形坐标必须按照 GeoJSON 的格式进行定义,也就是一个嵌套数组的形式。
除了 `geo_distance` 和 `geo_bounding_box` 查询,Elasticsearch 还支持一系列其他的地理位置查询方式,比如 `geo_polygon` 查询、`geo_shape` 查询等。你可以根据具体的查询需求来选择使用。同时,使用地理位置查询时需要特别注意性能问题,因为计算和缓存地理数据需要大量的内存和计算资源。
Elasticsearch 支持两种类型的地理位置查询:
geo_point
和geo_shape
。使用geo_point
类型的字段,可以通过geo_distance
查询或geo_bounding_box
查询来查找距离某个地理点一定距离内的文档;使用geo_shape
类型的字段,可以创建各种形状的地理围栏,包括圆、矩形、多边形、线等,然后可以使用geo_shape
查询来查找与这些围栏相交或包含的文档。同时,在使用地理位置查询时需要注意性能问题。