【ElasticSearch】深入探索 DSL 查询语法,实现对文档不同程度的检索,以及对搜索结果的排序、分页和高亮操作

news2024/11/17 4:27:19

文章目录

  • 前言
  • 一、Elasticsearch DSL Query 的分类
  • 二、全文检索查询
    • 2.1 `match` 查询
    • 2.2 `multi_match` 查询
  • 三、精确查询
    • 3.1 term 查询
    • 3.2 range 查询
  • 四、地理坐标查询
    • 4.1 geo_bounding_box 查询
    • 4.2 geo_distance 查询
  • 五、复合查询
    • 5.1 function score 查询
    • 5.2 boolean 查询
  • 六、对搜索结果的处理
    • 6.1 对搜索结果进行排序
    • 6.2 对搜索结果进行分页
    • 6.3 对搜索结果中的搜索关键字高亮处理

前言

Elasticsearch(简称ES)是一个强大的开源搜索和分析引擎,广泛应用于各种应用程序中,从企业级搜索引擎到日志和指标分析。其强大之处在于其灵活的数据模型和丰富的查询语言,使得用户能够轻松地进行全文检索、精确查询、地理坐标查询等操作。

本文将深入探讨Elasticsearch的DSL(Domain Specific Language)查询,分为多个部分进行介绍。首先,我们会了解Elasticsearch DSL Query的分类,然后深入研究全文检索查询、精确查询、地理坐标查询以及复合查询等不同类型的查询。

每一节都会提供详细的语法和实际示例,以便读者能够更好地理解和运用Elasticsearch中强大的查询功能。最后,我们将介绍对搜索结果进行排序、分页以及搜索关键字高亮处理等实用的处理技巧,以完善搜索体验。

让我们开始深入探讨Elasticsearch DSL Query,发现如何利用其强大的功能来提升搜索和分析的效果。

一、Elasticsearch DSL Query 的分类

Elasticsearch 提供了强大而灵活的DSL(领域特定语言)查询,用于定义对索引库中文档的不同类型查询。下面将详细介绍一些常见的 DSL查询类型:

1. 查询所有 - match_all

查询所有文档,通常用于测试或获取整个索引的文档。

{
  "query": {
    "match_all": {}
  }
}

2. 全文检索查询

  • match 查询

利用分词器对用户输入的内容进行分词,然后在索引中匹配分词后的词语。

{
  "query": {
    "match": {
      "field_name": "search_text"
    }
  }
}
  • multi_match 查询

在多个字段上执行全文检索查询。

{
  "query": {
    "multi_match": {
      "query": "search_text",
      "fields": ["field1", "field2"]
    }
  }
}

3. 精确查询

  • ids 查询

根据文档ID查询文档。

{
  "query": {
    "ids": {
      "values": ["doc_id1", "doc_id2"]
    }
  }
}
  • term 查询

根据精确词条值查找数据,适用于 keyword、数值、日期、boolean等类型字段。

{
  "query": {
    "term": {
      "field_name": "exact_value"
    }
  }
}
  • range 查询

根据范围查询,适用于数值、日期等类型的范围查询。

{
  "query": {
    "range": {
      "field_name": {
        "gte": "start_value",
        "lte": "end_value"
      }
    }
  }
}

4. 地理查询

  • geo_distance 查询

根据经纬度查询指定距离范围内的文档。

{
  "query": {
    "geo_distance": {
      "distance": "10km",
      "location": {
        "lat": 40.73,
        "lon": -73.98
      }
    }
  }
}
  • geo_bounding_box 查询

根据指定的矩形框查询文档。

{
  "query": {
    "geo_bounding_box": {
      "location": {
        "top_left": {
          "lat": 40.73,
          "lon": -74.1
        },
        "bottom_right": {
          "lat": 40.01,
          "lon": -71.12
        }
      }
    }
  }
}

5. 复合查询

  • bool 查询

通过组合多个查询条件,支持must、must_not、should等逻辑。

{
  "query": {
    "bool": {
      "must": [
        { "match": { "field1": "value1" } },
        { "range": { "field2": { "gte": 10, "lte": 20 } } }
      ],
      "must_not": [
        { "term": { "field3": "value2" } }
      ],
      "should": [
        { "match": { "field4": "value3" } }
      ]
    }
  }
}
  • function_score 查询

根据某个函数计算的分数对查询结果进行打分,用于加权不同的查询条件。

{
  "query": {
    "function_score": {
      "query": { "match": { "field": "search_text" } },
      "functions": [
        {
          "filter": { "range": { "field2": { "gte": 10, "lte": 20 } } },
          "weight": 2
        }
      ],
      "score_mode": "multiply"
    }
  }
}

以上是一些常见的 Elasticsearch DSL查询类型,在使用的时候可以根据具体需求灵活组合这些查询条件来实现复杂的搜索和过滤功能。下面是针对于这些不同查询的详细说明以及查询演示。

二、全文检索查询

全文检索查询是通过对用户输入的内容进行分词,然后在索引中匹配分词后的词语,实现更灵活的文本搜索。在Elasticsearch中,常用的关键词是 matchmulti_match

2.1 match 查询

match查询会根据一个字段进行查询,适用于单一字段的全文检索。在实际应用中,可以使用 copy_to 将多个字段的值合并到一个字段,从而实现类似 multi_match 的查询效果。

例如,针对 hotel 索引库的全文检索查询:

GET /hotel/_search
{
  "query": {
    "match": {
      "all": "如家"
    }
  }
}

这里假设 all 字段是通过 copy_to 包含了多个字段的内容,如:“brand”、“business”、“name”。查询结果如下:

match查询结果

2.2 multi_match 查询

multi_match查询允许根据多个字段进行全文检索查询,但需要注意,参与查询的字段越多,查询效率可能越低。

例如,使用 multi_match 查询:

GET /hotel/_search
{
  "query": {
    "multi_match": {
      "query": "如家",
      "fields": ["brand", "business", "name"]
    }
  }
}

在这个例子中,参与查询的字段同样是:“brand”、“business”、 “name”。查询结果如下:

multi_match查询结果

可以观察到,matchmulti_match 的查询结果是相同的。在实际应用中,选择使用哪种方式要根据具体需求和性能考虑来决定。

三、精确查询

精确查询是搜索引擎中常用的查询方式,特别适用于针对关键字、数值、日期、boolean等类型字段的精准检索。在酒店订购网站等应用中,用户通常希望根据特定的条件,如城市、星级、品牌、价格范围等,进行准确的信息检索。

下面将介绍在 Elasticsearch 中如何使用 termrange 进行精确查询。

3.1 term 查询

term 查询用于根据词条的精确值进行查询。例如,在酒店订购网站中,用户希望查找位于上海的所有酒店,可以使用以下 DSL 语句:

GET /hotel/_search
{
  "query": {
    "term": {
      "city": {
        "value": "上海"
      }
    }
  }
}

查询结果:

上述查询返回了所有城市为上海的酒店信息。然而,要注意的是,term 查询对查询关键字的精确匹配要求较高。如果将查询的值更改为 “上海北京”,将找不到匹配的结果:

因此,在使用 term 查询时,务必确保查询的关键字是准确的。

3.2 range 查询

range 查询用于根据值的范围进行查询,特别适用于数值型字段,比如价格范围。例如,用户希望查找价格在 100 到 200 之间的酒店,可以使用以下 DSL 语句:

GET /hotel/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 100,
        "lte": 200
      }
    }
  }
}

查询结果:

在上述查询中,使用了 gte 表示大于等于某个值,而 lte 表示小于等于某个值。通过这样的查询,可以精确地获取符合价格范围的酒店信息。

总的来说,精确查询在搜索引擎中是非常常用且实用的功能,通过合理使用 termrange 查询,可以满足用户对于准确信息检索的需求。

四、地理坐标查询

地理坐标查询是 Elasticsearch 中常见的功能之一,特别适用于需要根据地理位置信息进行搜索的场景,如查询附近的酒店、出租车、或者附近的人。下面介绍两种常用的地理坐标查询方式:geo_bounding_boxgeo_distance

4.1 geo_bounding_box 查询

geo_bounding_box 查询用于查询 geo_point 值在某个矩形范围内的所有文档。以下是一个示例:

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

在这个例子中,通过指定矩形的左上角和右下角的经纬度,可以查询所有位置在这个矩形范围内的文档。

搜索范围示意图,形状为矩形:

4.2 geo_distance 查询

geo_distance 查询用于查询到指定中心点距离小于某个距离值的所有文档。以下是一个示例:

GET /indexName/_search
{
  "query": {
    "geo_distance": {
      "distance": "15km",
      "FIELD": "31.21,121.5"
    }
  }
}

在这个例子中,通过指定中心点的经纬度和距离值,可以查询所有距离中心点小于 15 公里的文档。

搜索范围示意图,形状为圆:

通过这两种方式,可以在地理坐标信息中实现灵活而精确的查询,满足用户在不同应用场景下的位置搜索需求。

五、复合查询

复合(compound)查询可以将其它简单查询组合起来,实现更复杂的搜索逻辑,例如:

  • function score: 算分函数查询,可以控制文档相关性算分,控制文档排名,类似于百度搜索结果中一些顶置的广告。

  • Boolean Query:布尔查询,一个或多个查询子句的组合,子查询的组合方式有:

    • must:必须匹配每个子查询,类似“与”。
    • should:选择性匹配子查询,类似“或”。
    • must_not:必须不匹配,不参与算分,类似“非”。
    • filter:必须匹配,不参与算分。

5.1 function score 查询

假设,现在文档中有一些是广告,我们希望这些广告在查询结果中是最靠前的,因此可以使用 function score 查询来修改特定文档的打分,例如,给“如家”这个品牌的酒店排名靠前一定:

为了实现这个目标,我们需要提供以下三个要素:

  1. 哪些文档需要算分加权?

    • 品牌为如家的酒店。
  2. 算分函数是什么?

    • weight
  3. 加权模式是什么?

    • 乘积。

查询 DSL 语句如下:

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

说明:

  • query :原始查询条件,搜索文档并根据相关性打分(query score)。
  • filter:过滤条件,符合条件的文档才会被重新算分。
  • weight:算分函数,算分函数的结果称为 function score ,将来会与 query score 运算,得到新算分。常见的算分函数有:
    • weight:给一个常量值,作为函数结果(function score)。
    • field_value_factor:用文档中的某个字段值作为函数结果。
    • random_score:随机生成一个值,作为函数结果。
    • script_score:自定义计算公式,公式结果作为函数结果。
  • boost_mode:加权模式,定义 function score 与 query score 的运算方式,包括:
    • multiply:两者相乘。默认就是这个。
    • replace:用 function score 替换 query score。
    • 其它:sumavgmaxmin

查询结果:
Function Score Query Result

5.2 boolean 查询

例如,现在有一个查询需求:搜索名字包含“如家”,价格不高于400,在坐标31.21,121.5周围 10km 范围内的酒店。

GET /hotel/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "如家"
          }
        }
      ],
      "must_not": [
        {
          "range": {
            "price": {
              "gte": 400
            }
          }
        }
      ],
      "filter": [
        {
          "geo_distance": {
            "distance": "10km",
            "location": {
              "lat": 31.21,
              "lon": 121.5
            }
          }
        }
      ]
    }
  }
}

说明:

  • must:必须匹配每个子查询,类似“与”。
  • must_not:必须不匹配,不参与算分,类似“非”。
  • filter:必须匹配,不参与算分。

搜索结果:

Boolean Query Result

通过这个例子,我们可以看到如何使用布尔查询来组合多个条件,实现更精确的搜索。

六、对搜索结果的处理

6.1 对搜索结果进行排序

ElasticSearch 支持对搜索结果排序,默认是根据相关度算分(_score)来排序。可以排序字段类型有:keyword 类型、数值类型、地理坐标类型、日期类型等。

示例一:对酒店数据按照用户评价降序排序,评价相同的按照价格升序排序

评价是 score 字段,价格是 price 字段,按照顺序添加两个排序规则即可。

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

示例二:实现对酒店数据按照到(121.507712,31.224612)的位置坐标的距离升序排序

获取经纬度的方式:https://lbs.amap.com/demo/jsapi-v2/example/map/click-to-get-lnglat/。

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

6.2 对搜索结果进行分页

ElasticSearch 默认情况下只返回 top 10 的数据。而如果要查询更多数据就需要修改分页参数了。ElasticSearch 中通过修改 fromsize 参数来控制要返回的分页结果。

基本语法如下:

GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "from": 990, // 分页开始的位置,默认为0
  "size": 10, // 期望获取的文档总数
  "sort": [
    {"price": "asc"}
  ]
}

示例:使用 match_all 查询,然后对结果进行分页

GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "from": 0,
  "size": 5
}

搜索结果,现在就只展示5条结果了:

分页结果

深度分页问题:

ES是分布式的,所以会面临深度分页问题。例如按 price 排序后,获取 from = 990,size =10 的数据:

  1. 首先在每个数据分片上都排序并查询前1000条文档。
  2. 然后将所有节点的结果聚合,在内存中重新排序选出前1000条文档。
  3. 最后从这1000条中,选取从990开始的10条文档。

如果搜索页数过深,或者结果集(from + size)越大,对内存和 CPU 的消耗也越高。因此 ES 设定结果集查询的上限是10000。

深度分页解决方案:

针对深度分页,ES提供了两种解决方案:

  1. **search after:**分页时需要排序,原理是从上一次的排序值开始,查询下一页数据。官方推荐使用的方式。
  2. **scroll:**原理将排序数据形成快照,保存在内存。官方已经不推荐使用。

6.3 对搜索结果中的搜索关键字高亮处理

高亮处理,就是在搜索结果中把搜索关键字突出显示。

原理:

  • 将搜索结果中的关键字用标签标记出来。
  • 在页面中给标签添加 CSS 样式。

语法:

GET /hotel/_search
{
  "query": {
    "match": {
      "FIELD": "TEXT"
    }
  },
  "highlight": {
    "fields": {
      "FIELD": {
        "pre_tags": "<em>",  // 用来标记高亮字段的前置标签
        "post_tags": "</em>" // 用来标记高亮字段的后置标签
      }
    }
  }
}

示例:对搜索的品牌名称进行高亮处理

GET /hotel/_search
{
  "query": {
    "match": {
      "brand": "如家"
    }
  },
  "highlight": {
    "fields": {
      "brand": {
        "pre_tags": "<em>",
        "post_tags": "</em>"
      }
    }
  }
}

搜索结果:

高亮搜索结果

以上便是对ElasticSearch搜索结果进行排序、分页和关键字高亮处理的一些示例和基本操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1082721.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年中国溶瘤病毒药物上市产品、研发现状及行业市场规模前景[图]

溶瘤病毒&#xff08;Oncolyticvirus&#xff09;&#xff0c;是一类具有复制能力的肿瘤杀伤型病毒&#xff0c;溶瘤病毒根据所采用的毒株类型可以被分为天然病毒株&#xff08;野生型病毒株&#xff09;和基因改造病毒株两类&#xff0c;溶瘤病毒的种类也从最初的疱疹病毒发展…

使用c++视觉处理----canny 边缘检测、sobel边缘检测、scharr 滤波边缘检测

使用c视觉处理canny 边缘检测、sobel边缘检测、scharr 滤波边缘检测 #include <opencv2/opencv.hpp>int main() {// 读取图像cv::Mat image cv::imread("1.jpg", cv::IMREAD_GRAYSCALE); // 转为灰度图像if (image.empty()) {std::cerr << "无法加…

网络-网络状态网络速度

文章目录 前言一、网络状态二、网络速度 前言 本文主要记录如何监听网络状态和网络速度。 一、网络状态 获取当前网络状态: navigator.onLine // true:在线 false:离线监听事件&#xff1a;online&#xff08;联网&#xff09; 和 offline&#xff08;断网&#xff09; windo…

全国A级旅游景区清单数据(2023年更新)

全国A级旅游景区清单数据&#xff08;2023年更新&#xff09; 1.样本量&#xff1a;14847条 2.来源&#xff1a;政府公布资料 3.指标&#xff1a;景区名称、等级、所属省份、所属城市、所属区县、地址、当前等级评定时间、相关文件发布时间、坐标(GCJ02)Lng、坐标(GCJ02)Lat…

【Redis实战】分布式锁

分布式锁 synchronized只能保证单个JVM内部的线程互斥&#xff0c;不能保证集群模式下的多个JVM的线程互斥。 分布式锁原理 每个JVM内部都有自己的锁监视器&#xff0c;但是跨JVM&#xff0c;就会有多个锁监视器&#xff0c;就会有多个线程获取到锁&#xff0c;不能实现多JV…

分享一份关于 Rust 编程的学习指南

Rust是一种现代的系统级编程语言&#xff0c;以其注重内存安全、性能和并发性而闻名。学习Rust可以是一段有回报的旅程&#xff0c;为您打开构建强大高效应用的机会。无论您是经验丰富的开发者还是完全的初学者&#xff0c;本指南将通过精选的资源和技巧帮助您踏上Rust编程之旅…

【angular】实现简单的angular国际化(i18n)

文章目录 目标过程运行参考 目标 实现简单的angular国际化。本博客实现中文版和法语版。 将Hello i18n!变为中文版&#xff1a;你好 i18n!或法语版:Bonjour l’i18n !。 过程 创建一个项目&#xff1a; ng new i18nDemo在集成终端中打开。 添加本地化包&#xff1a; ng a…

景联文科技:3D点云标注应用场景和专业平台

3D点云技术之所以得到广泛发展和应用&#xff0c;主要是因为它能够以一种直观、真实和全面的方式来表示和获取现实世界中的三维信息。 3D点云的优势&#xff1a; 真实感和立体感&#xff1a;3D点云数据能够呈现物体的真实感和立体感&#xff0c;使观察者能够更直观地理解物体的…

Springboot整合阿里云OSS进行上传单个图片,多个图片,删除图片功能

1. 导入OSS依赖 <!-- 阿里云oss依赖 --><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.10.2</version></dependency> 2. 进行OSS配置 package com.example.sushe…

[GAMES101]透视投影变换矩阵中为什么需要改变z值

透视投影需要保证&#xff0c;1.变换矩阵内的元素是常数&#xff0c;2.相对深度值不变&#xff08;绝对值不重要&#xff09;&#xff1b;若再加上变换后zNear和zFar平面上的点依旧在zNear和zFar平面上这两个条件&#xff08;实际上并不一定需要满足这两个条件&#xff09;&…

机器人制作开源方案 | 扫地机器人

1. 功能描述 扫地机器人是现代家庭清洁的得力助手&#xff0c;能够自主规划清扫路径&#xff0c;避开障碍物&#xff0c;有效覆盖整个清洁区域。扫地机器人的出现极大地减轻了家庭清洁的负担&#xff0c;节省了时间和精力&#xff0c;它可以定期清理地面&#xff0c;确保家居环…

043:mapboxGL鼠标点击提示source属性信息

第043个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中通过鼠标点击提示source属性信息。这里用到了popup弹窗,用到了click事件,用到了鼠标样式的变化等功能。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源…

正点原子嵌入式linux驱动开发——Busybox根文件系统构建

前面已经移植了TF-A、Uboot和Linux kernel&#xff0c;就剩最后一个 rootfs(根文件系统)了&#xff0c;本章就来学习一下根文件系统的组成以及如何构建根文件系统。这是Linux系统移植的最后一步&#xff0c;根文件系统构建好以后就意味着拥有了一个完整的、可以运行的最小系统 …

【C语言】求解数独 求数独的解的个数 多解数独算法

目录 什么是数独&#xff1f; 数独的解法&#xff1f; 数独DFS算法详解 1. 初始化条件 2. 填入已初始化的数独表 3. 填数独 4. 拓展问题 请问删掉数独中的哪两个数可以使得数独的解最大&#xff1f; 删除的是哪两个数&#xff1f; 最终代码 main函数&#xff08;如何执行…

前端-uniapp-开发指南

美团外卖微信小程序开发 uniapp-美团外卖微信小程序开发P1 成果展示P2外卖小程序后端&#xff0c;学习给小程序写http接口P3 主界面配置P4 首页组件拆分P13 外卖列表布局筛选组件商家 布局测试数据创建样式 请求商家外卖数据封装请求并发请求 uni-app框架调用https接口 开发小程…

UE4和C++ 开发-C++绑定widget的方式和初始化UI

C绑定widget的方式有两种&#xff0c;一种是使用meta (BindWidget)&#xff0c;一种是使用GetWidgetFromName(TEXT("")),两种方式都可以。一、meta BindWidget方式 注意这种绑定的方式UMG里面的空间名称需要与C里面声明的变量名称相同 Btn_StartU 二、GetWidge…

成都瀚网科技有限公司:怎么优化抖店体验分?

近年来&#xff0c;抖音电商平台凭借强大的用户基础和广阔的销售渠道吸引了越来越多的商家入驻。然而&#xff0c;对于新手卖家来说&#xff0c;提高抖店经验值却成了一件头疼的事情。那么&#xff0c;如何优化抖店体验分呢&#xff1f;本文将从产品质量、服务态度、运营策略等…

Springboot集成MyBatis实现查询表操作(二)

目录 第一章、准备1.1&#xff09;准备数据库表1.2&#xff09;创建springboot项目&#xff0c;添加依赖1.3&#xff09;使用mybatis逆向工程 第二章、代码开发2.1&#xff09;建包并编写代码2.2&#xff09;application配置文件2.3&#xff09;设置编译位置 第三章、测试访问3…

【NUMA平衡】浅入介绍NUMA平衡技术及调度方式

在云计算方案设计或项目问题处理的时候&#xff0c;经常会遇到NUMA平衡的问题&#xff0c;进行让人不清楚NUMA到底有何用&#xff0c;如何发挥作用&#xff0c;本文就NUMA技术原理和调度进行简要整理&#xff0c;方便后续需要时候查阅学习。 一.背景 一般的对称多处理器中&am…

基于SpringBoot的新闻稿件管理系统

目录 前言 一、技术栈 二、系统功能介绍 管理员模块的实现 用户信息管理 记者信息管理 审批员信息管理 记者模块的实现 新闻信息管理 审批员模块的实现 新闻信息管理 用户模块的实现 新闻信息 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信…