SpringCloud——分布式搜索elasticsearch之DSL查询语句的使用

前言:
Elasticsearch(ES)是一个分布式的开源搜索和分析引擎,它提供了一个强大的查询语言,称为领域特定语言(Domain-Specific Language,DSL)。ES的DSL查询语言允许我们以更灵活和精确的方式来查询和操作存储在Elasticsearch索引中的数据。
本文介绍了DSL查询语句的使用。
官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/8.8/indices.html



1、DSL的查询分类

在Elasticsearch(ES)中,DSL(领域特定语言)查询根据其功能和用途可以进行分类。以下是ES中DSL查询的常见分类:

全文检索(full text)查询:利用分词器对用户输入内容分词,然后去倒排索引库中匹配。

  • match_query
  • multi_match_query

精确查询:根据精确词条值查找数据,一般是查找keyword、数值、日期、boolean等类型字段。

  • ids
  • range
  • term

地理(geo)查询:根据经纬度查询。

  • geo_distance
  • geo_bounding_box

复合(compound)查询︰复合查询可以将上述各种查询条件组合起来,合并查询条件。

  • bool
  • function_score

本文中用到的索引库都在文章: http://t.csdn.cn/nembv

2、全文检索查询

前言:全文检索(Full-text search)查询是一种用于在文本数据中执行复杂搜索的查询方法,旨在找到与查询字符串最匹配的文档。在Elasticsearch中,可以使用全文检索查询来执行全文搜索和相关性评分。

1、Match查询
全文检索查询的一种,会对用户输入内容分词,然后去倒排索引库检索,根据相关性评分返回与查询字符串匹配的文档。

扫描二维码关注公众号,回复: 17280212 查看本文章
GET /索引库名/_search
{
    
    
  "query": {
    
    
    "match": {
    
    
      "字段值": "搜索值"
    }
  }
}

以hotel索引库为例:

GET /hotel/_search
{
    
    
   "query": {
    
    
    "match": {
    
    
      "city": "尔海"
    }
  }
}

当执行上述查询时,Elasticsearch将对查询字符串"尔海"进行分词处理。默认情况下,Elasticsearch使用内置的分析器(analyzer)来处理文本字段的分词,通常是使用标准分析器(standard analyzer)很明显"尔海"j将被分词为:尔、海 然后进行查询。在这里插入图片描述2、Multi-match查询

在多个字段中执行文本匹配查询,根据相关性评分返回匹配的文档。

GET /索引库名/_search
{
    
    
  "query": {
    
    
  "multi_match": {
    
    
      "query": "搜索值",
      "fields": ["字段1", "字段2"]
    }
  }
}

将返回字段1、字段2中与查询字符串 “搜索值” 最匹配的文档,根据相关性评分进行排序。

GET /hotel/_search
{
    
    
  "query": {
    
    
  "multi_match": {
    
    
      "query": "上海",
      "fields": ["address", "name"]
    }
  }
}

上述示例会对上海进行分词操作,在字段address、name中进行查询,按照相关性返回查询结果:
在这里插入图片描述2、全部查询 match_all
查询出所有数据,一般测试用。match_all
#查询所有

GET hotel/_search
{
    
    
  "query": {
    
    
    "match_all": {
    
    
    }
  }
}

在这里插入图片描述

3、精确查询

前言:精确查询是一种在搜索引擎中执行精确匹配的查询方法,它用于查找与指定词条值完全相等的文档。在Elasticsearch中,可以使用不同的查询类型来执行精确查询,具体取决于查询的字段类型和需求。

1、term查询

term查询用于执行精确匹配查询,可以匹配一个字段中与指定值完全相等的文档。

GET /索引库名/_search
{
    
    
  "query": {
    
    
    "term": {
    
    
      "field": {
    
    
        "value": "value"
      }
    }
  }
}

上述示例将匹配具有"field"字段值等于"value"的文档。
eg:

# 精确查询城市为上海的酒店
GET /hotel/_search
{
    
    
  "query": {
    
    
    "term": {
    
    
      "city": {
    
    
        "value": "上海"
      }
    }
    }
  }
}

在这里插入图片描述

terms查询用于匹配指定字段中包含多个精确值的文档。它类似于term查询,但可以一次匹配多个值。

GET /索引库名/_search
{
    
    
  "query": {
    
    
    "terms": {
    
    
      "field": [
        "v1",
        "v2"
      ]
    }
    }
  }
}

上述示例将匹配具有"field"字段值为"v1"、"v2"的文档。

略。。。。。。

2、range查询

前言:range查询是一种在Elasticsearch中进行范围查询的查询类型。它允许您匹配一个字段中处于指定范围内的值。range查询可以应用于各种类型的字段,如数值、日期等。

下面是range查询的一般语法和用法示例:

# range 查询
GET /索引库名/_search 
{
    
    
  "query": {
    
    
    "range": {
    
    
      "FIELD": {
    
    
        "gte": 10,
        "lte": 20
      }
    }
  }
}

上述代码将查询字段FIELD值在10到20之间的所有数据。

注意:在执行range查询时,可以使用不同的操作符来指定范围条件,如大于(gt)、小于(lt)、大于等于(gte)、小于等于(lte)等。根据实际需求,您可以调整查询条件来满足特定的范围查询要求。

# range 查询hotel索引库中价格在500~1000之间的所有酒店
GET /hotel/_search 
{
    
    
  "query": {
    
    
    "range": {
    
    
      "price": {
    
    
        "gte": 500,
        "lte": 1000
      }
    }
  }
}

在这里插入图片描述

4、地理坐标查询

前言:地理坐标查询是一种在Elasticsearch中执行基于地理位置信息的查询的方法。它允许根据地理坐标或地理形状来搜索和过滤文档。Elasticsearch使用地理坐标索引和GeoJSON格式来处理地理数据。

1、geo_bounding_box查询:

geo_bounding_box查询用于搜索位于指定矩形边界框内的地理位置。
下面是geo_bounding_box查询的一般语法和用法示例:

GET /索引库名/_search
{
    
    
  "query": {
    
    
    "geo_bounding_box": {
    
    
      "field": {
    
    
        "top_left": {
    
    
          "lat": top_left_lat,
          "lon": top_left_lon
        },
        "bottom_right": {
    
    
          "lat": bottom_right_lat,
          "lon": bottom_right_lon
        }
      }
    }
  }
}

在上述示例中,field是包含经纬度坐标的字段名,top_left和bottom_right分别指定了矩形边界框的西北角和东南角的经纬度坐标。geo_bounding_box查询可用于快速过滤位于指定矩形区域内的地理位置数据。(在Elasticsearch中的地理坐标查询中,经度使用lon(longitude)表示,纬度使用lat(latitude)表示。经度在查询语句中通常出现在lon字段中,纬度出现在lat字段中。)

eg:我们查找地图坐标在 (121.5,31.1) (121.7,30.9)范围内的所有文档:

GET /hotel/_search
{
    
    
  "query": {
    
    
    "geo_bounding_box": {
    
    
      "location": {
    
    
        "top_left": {
    
    
          "lat": 31.1,
          "lon": 121.5
        },
        "bottom_right": {
    
    
          "lat": 30.9,
          "lon": 121.7
        }
      }
    }
  }
}

在这里插入图片描述2、geo_distance查询:
geo_distance查询是一种在Elasticsearch中用于根据指定的中心点和距离范围搜索地理位置的查询类型。它允许我们找到位于指定距离内的地理位置数据。

GET /索引库名/_search
{
    
    
  "query": {
    
    
    "geo_distance": {
    
    
      "distance": "d1",
      "location": "lat,lon"
    }
  }
}

上述代码查询在经纬度坐标为(lon,lat)范围d1距离内的所有文档数据。
eg:
查询坐标为(121.5,31.21)范围15km的所有酒店数据

#distance 查询
GET /hotel/_search
{
    
    
  "query": {
    
    
    "geo_distance": {
    
    
      "distance": "15km",
      "location": "31.21,121.5"
    }
  }
}

在这里插入图片描述

5、复合查询

前言:复合查询是指在Elasticsearch中使用多个查询条件结合起来进行查询的方式。通过组合不同类型的查询,可以更精确地筛选出符合多个条件的文档。Elasticsearch提供了bool查询来支持组合查询。bool查询通过逻辑运算符(如must、must_not、should、filter等)将多个查询条件组合在一起。

1、算分函数查询(Function Score Query)

算分函数查询(Function Score Query)是一种在Elasticsearch中用于自定义文档评分(Scoring)的查询类型。它允许您基于自定义的算分函数来调整文档的相关性评分,以满足特定的搜索需求。
Function Score Query使用一个或多个函数来调整文档的得分。这些函数可以是各种算分函数。
以下是一个Function Score Query的示例:

GET /索引库名/_search
{
    
    
  "query": {
    
    
    "function_score": {
    
    
      "query": {
    
    
        "match": {
    
    
          "description": "elasticsearch"
        }
      },
      "functions": [
        {
    
    
          "weight": 2,
          "filter": {
    
    
            "term": {
    
    
              "category": "technology"
            }
          }
        },
        {
    
    
          "field_value_factor": {
    
    
            "field": "popularity",
            "factor": 0.1,
            "modifier": "sqrt"
          }
        }
      ],
      "score_mode": "sum",
      "boost_mode": "multiply"
    }
  }
}

下面对上文的代码进行解释:
function_score:指定了Function Score Query的查询类型。
query:指定了要进行评分的子查询,这里使用了一个简单的match查询,意思是查询出字段为description值为elasticsearch的文档。
functions:指定了要应用于文档得分的函数列表。

函数一
filter、weight:过滤条件,只有符合的文档才会被重新算分,这里使用了精确查找,查找所有category为technology的文档,使用的算分函数是weight,权重函数,给一个常量值作为函数结果。

函数二
这里是使用了字段值因子函数(Field Value Factor Function)来调整文档的得分,具体来说就是使用文档中某个字段的值作为函数结果,下面是这段函数的解释:

field:指定要使用的字段名称,这里是popularity字段。该字段的值将用于计算得分。
factor:指定一个因子值,用于调整字段值的影响程度。在示例中,因子值为0.1,表示将popularity字段的值乘以0.1。
modifier:指定一个修饰符,用于调整函数的计算方式。在示例中,修饰符为sqrt,表示对调整后的字段值进行平方根计算。

score_modeboost_mode是Function Score Query的两个参数,用于控制函数得分和查询得分的组合方式。

score_mode:指定多个函数得分的组合方式。可选的取值包括:

  • sum:将多个函数得分相加,得到最终的文档得分。
  • avg:计算多个函数得分的平均值,作为最终的文档得分。
  • max:选择多个函数得分中的最大值作为最终的文档得分。
  • min:选择多个函数得分中的最小值作为最终的文档得分。
  • multiply:将多个函数得分相乘,得到最终的文档得分。

boost_mode:指定函数得分和查询得分的组合方式。可选的取值包括:

  • multiply:将函数得分与查询得分相乘,得到最终的文档得分。
  • replace:仅使用函数得分,忽略查询得分。
  • sum:将函数得分和查询得分相加,得到最终的文档得分。
    在上述代码中score_mode设置为sum,表示将多个函数得分相加,得到函数得分,同时boost_mode设置为multiply,表示将函数得分与查询得分相乘,得到最终的文档得分。

案例:给如家这个品牌的酒店靠前一点。
在这里插入图片描述
现在我们使用算分函数查询(Function Score Query)让我们查询出来的数据如家排在前面:

GET /hotel/_search
{
    
    
  "query": {
    
    
    "function_score": {
    
    
      "query": {
    
    
        "match": {
    
    
          "all": "外滩"
        }
      },
      "functions": [
        {
    
    
          "filter": {
    
    
            "term": {
    
    
              "brand": "如家"
            }
          }
          , "weight": 10
        }
      ],
      "boost_mode": "multiply"
    }
  }
}

在这里插入图片描述

2、布尔查询(Boolean Query)

前言:布尔查询(Boolean Query)是一种在Elasticsearch中使用的复合查询类型,它允许您通过组合多个子查询来构建更复杂和灵活的查询逻辑。布尔查询使用逻辑运算符(AND、OR、NOT)来定义子查询之间的关系,以及它们对文档的匹配条件。

布尔查询支持以下三种逻辑运算符:

MUST(AND):所有的子查询都必须匹配文档才会被包含在结果中。这类似于逻辑运算中的AND操作符。只有当所有子查询都匹配时,文档才会被视为匹配。

SHOULD(OR):至少有一个子查询匹配文档,文档才会被包含在结果中。这类似于逻辑运算中的OR操作符。如果有多个子查询匹配,Elasticsearch会根据相关性评分确定文档的排名。

MUST_NOT(NOT):子查询不应该匹配文档,否则该文档将被排除在结果中。这类似于逻辑运算中的NOT操作符。MUST_NOT子查询通常用于排除特定条件的文档,不参与算分。
FILTER:必须匹配,不参与算分。
案例:

GET /hotel/_search
{
    
    
  "query": {
    
    
    "bool": {
    
    
      "must": [
        {
    
    
          "term": {
    
    
            "city": {
    
    
              "value": "上海"
            }
          }
        }
      ],
      "should": [
        {
    
    
          "term": {
    
    
            "brand": {
    
    
              "value": "速8"
            }
          }
        },
        {
    
    
          "term": {
    
    
            "brand": {
    
    
              "value": "如家"
            }
          }
        }
      ],
      "must_not": [
        {
    
    
          "range": {
    
    
            "price": {
    
    
              "lte": 500
            }
          }
        }
      ],
      "filter": [
        {
    
    
          "range": {
    
    
            "score": {
    
    
              "gte": 45
            }
          }
        }
      ]
    }
  }
}

上述代码中我们搜索的是地区在上海的,品牌包括皇冠假日、君悦 价格小于500的 评分不低于45分的酒店。在这里插入图片描述

6、查询结果排序

前言:在Elasticsearch中,我们可以通过指定排序方式来对查询结果进行排序。
可以排序的字段类型有:keyword类型、数值类型、地理坐标类型、日期类型等。
默认情况下Elasticsearch会根据查询的相关性得分对文档进行排序,以便将与查询最相关的文档排在前面。
相关性得分是根据匹配查询条件的程度和其他因素计算的,Elasticsearch会自动处理。

简单字段排序

GET /索引库名/_search
{
    
    
  "query": {
    
    
    "match_all": {
    
    }
  },
  "sort": [
    {
    
    
      "FIELD": {
    
    
        "order": "desc"
      }
    }
  ]
}

上述代码是一个简单字段排序,我们将搜索到的结果按照字段FIELD的降序排序

eg1:将查询到的酒店按照价格降序排序

# 将查询到的酒店按照价格降序排序
GET /hotel/_search
{
    
    
  "query": {
    
    
    "match_all": {
    
    }
  },
  "sort": [
    {
    
    
      "price": {
    
    
        "order": "desc"
      }
    }
  ]
}

在这里插入图片描述eg2:将查询到的酒店按照价用户评价升序排序、价格降升序排序

GET /hotel/_search
{
    
    
  "query": {
    
    
    "match_all": {
    
    }
  },
  "sort": [
    {
    
    
      "score": {
    
    
        "order": "desc"
      },
      "price": {
    
    
        "order": "asc"
      }
    }
  ]
}

在这里插入图片描述eg3:按照我们的位置坐标距离升序对酒店进行排序(寻找我们附近的酒店,距离升序排序)假设我们经纬度是坐标是:(121.6 ,31.03)

GET /hotel/_search
{
    
    
  "query": {
    
    
    "match_all": {
    
    }
  },
  "sort": [
    {
    
    
      "_geo_distance": {
    
    
        "location": {
    
    
          "lat": 31.03,
          "lon": 121.6
        }, 
        "order": "asc",
        "unit": "km"
      }
    }
  ]
}

在这里插入图片描述注意:一但进行了排序就不会在进行相关性算分。

6、查询结果分页

在Elasticsearch中,分页是指对查询结果进行分块返回,以便在大数据集中显示有限数量的结果。分页可以帮助我们控制结果集的大小,并实现结果的分段加载。默认情况下Elasticsearch只会返回前十条数据,而查询更多数据就需要修改分页参数了。

Elasticsearch使用两个参数来实现分页:

from:指定要返回的结果的起始位置。默认值为0,表示从第一个结果开始返回。例如,如果我们设置from为10,那么返回的结果将从第11个结果开始。

size:指定每页返回的结果数量。默认值为10。例如,如果我们设置size为20,那么每页将返回20个结果。

GET /索引库名/_search
{
    
    
  "query": {
    
    
    "match_all": {
    
    }
  },
  "from": 0,
  "size": 10
}

eg:查询出前5条酒店数据,按照价格升序排序

GET /hotel/_search
{
    
    
  "query": {
    
    
    "match_all": {
    
    }
  },
  "sort": [
    {
    
    
      "price": {
    
    
        "order": "asc"
      }
    }
  ],
  "from": 0,
  "size": 5
}

在这里插入图片描述

深分页问题

前言:深分页问题是指在Elasticsearch中对大量数据进行分页操作时可能面临的一些性能和资源消耗方面的问题。
默认情况下,Elasticsearch对于大于10000的from值进行了限制,这是为了避免深度分页操作对系统性能产生不利影响。这个限制是为了保护集群的稳定性和性能,因为在分布式环境下,每个分片都需要执行跳过操作,这会增加查询的开销和资源消耗。

解决方案:

index.max_result_window设置:可以通过更改集群级别的index.max_result_window设置来提高深分页的限制。但是,这样做可能会增加系统的负担和资源消耗。因此,建议谨慎使用,特别是在处理大量数据时。

使用游标(scroll):游标是一种高效的分页方式,适用于需要快速滚动浏览大量结果的场景。通过使用scroll API生成一个可供后续请求使用的游标标识符,可以避免对大的from值进行跳过操作,从而避免深分页问题。

使用搜索排序字段(search_after):使用搜索排序字段可以用于在分页过程中进行游标操作,类似于游标的方式。通过在每个分页请求中使用上一页结果的排序字段值作为search_after参数,可以在不使用from值的情况下获取下一页的结果。

6、查询结果高亮

在Elasticsearch中,您可以使用高亮(highlighting)功能来突出显示匹配查询条件的文本片段,以便在搜索结果中更直观地展示关键词的位置。

GET /索引库名/_search
{
    
    
  "query": {
    
    
    "match": {
    
    
      "字段名": "关键词"
    }
  },
  "highlight": {
    
    
    "fields": {
    
    
      "字段名": {
    
    }
    }
  }
}

eg:搜索如家酒店,并将name字段的内容高亮

GET /hotel/_search
{
    
    
  "query": {
    
    
    "match": {
    
    
      "all": "如家"
    }
  },
  "highlight": {
    
    
    "fields": {
    
    
      "name": {
    
    
        "require_field_match": "false"
      }
    }
  }
}

在这里插入图片描述
注意:在Elasticsearch中,require_field_match参数用于控制高亮功能是否仅在匹配查询条件的字段上进行操作。

当require_field_match设置为true时(默认值),高亮功能只会在匹配查询条件的字段上进行操作。这意味着如果查询条件与某个字段不匹配,即使该字段中包含了关键词,该字段也不会被高亮显示。

但是,当require_field_match设置为false时,高亮功能将在所有字段上执行,而不管是否匹配查询条件。这意味着无论查询条件是否与字段匹配,只要字段中包含了关键词,它就会被高亮显示。

在上文中我们查询字段是all但是高亮字段是name,查询字段跟高亮字段不一致,默认不会高亮显示,所以我们需要将require_field_match设置为false,以便于name字段查询的数据可以高亮显示。

猜你喜欢

转载自blog.csdn.net/qq_52227892/article/details/131074988
今日推荐