别只会搜日志了,求你懂点检索原理吧(五)之 高阶检索玩法

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
日志服务 SLS,月写入数据量 50GB 1个月
简介: 别只会搜日志了,求你懂点检索原理吧(五)之 高阶检索玩法

五、高阶检索玩法

5.1 两种查询方式

5.1.1 URL 后接参数

GET bank/_search?q=*&sort=account_number: asc

`/_search?q=*&sort=account_number: asc`

查询出所有数据,共 1000 条数据,耗时 1ms,只展示 10 条数据 ( ES 分页 )

URL 后接参数

属性值说明:

took – ES 执行搜索的时间 ( 毫秒 )
timed_out – ES 是否超时
_shards – 有多少个分片被搜索了,以及统计了成功/失败/跳过的搜索的分片
max_score – 最高得分
hits.total.value - 命中多少条记录
hits.sort - 结果的排序 key 键,没有则按 score 排序
hits._score - 相关性得分
参考文档:
https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started-search.html

5.1.2 URL 加请求体进行检索 ( QueryDSL )

请求体中写查询条件

语法:

GET bank/_search
{
  "query":{"match_all": {}},
  "sort": [
    {"account_number": "asc" }
 ]
}

示例:查询出所有,先按照 accout_number 升序排序,再按照 balance 降序排序

URL 加请求体进行检索

5.2 详解 QueryDSL 查询

DSL: Domain Specific Language

5.2.1 全部匹配 match_all

示例:查询所有记录,按照 balance 降序排序,只返回第 11 条记录到第 20 条记录,只显示 balance 和 firstname 字段。

GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
 {
      "balance": {
        "order": "desc"
 }
 }
  ],
  "from": 10,
  "size": 10,
  "_source": ["balance", "firstname"]
}

5.2.2 匹配查询 match

  • 基本类型 ( 非字符串 ) ,精确匹配
GET bank/_search
{
  "query": {
    "match": {"account_number": "30"}
 }
}
  • 字符串,全文检索
GET bank/_search
{
  "query": {
    "match": {
      "address": "mill road"
 }
 }
}

字符串全文检索

全文检索按照评分进行排序,会对检索条件进行分词匹配。

查询 address 中包含 mill 或者 road 或者 mill road 的所有记录,并给出相关性得分。

查到了 32 条记录,最高的一条记录是 Address = "990 Mill Road",得分:8.926605. Address="198 Mill Lane" 评分 5.4032025,只匹配到了 Mill 单词。

5.2.3 短语匹配 match_phase

将需要匹配的值当成一个整体单词 ( 不分词 ) 进行检索

GET bank/_search
{
  "query": {
    "match_phrase": {
      "address": "mill road"
 }
 }
}
查出 address 中包含 mill road 的所有记录,并给出相关性得分

5.2.4 多字段匹配 multi_match

GET bank/_search
{
  "query": {
    "multi_match": {
      "query": "mill land",
      "fields": [
        "state",
        "address"
 ]
 }
 }
}
multi_match 中的 query 也会进行分词。

查询 state 包含 millland 或者 address 包含 millland 的记录。

5.2.5 复合查询 bool

复合语句可以合并任何其他查询语句,包括复合语句。复合语句之间可以相互嵌套,可以表达复杂的逻辑。

搭配使用 must,must_not,should

must: 必须达到 must 指定的条件。 ( 影响相关性得分 )

must_not: 必须不满足 must_not 的条件。 ( 不影响相关性得分 )

should: 如果满足 should 条件,则可以提高得分。如果不满足,也可以查询出记录。 ( 影响相关性得分 )

示例:查询出地址包含 mill,且性别为 M,年龄不等于 28 的记录,且优先展示 firstname 包含 Winnie 的记录。

GET bank/_search
{
  "query": {
    "bool": {
      "must": [
 {
          "match": {
            "address": "mill"
 }
        },
 {
          "match": {
            "gender": "M"
 }
 }
      ],
      "must_not": [
 {
          "match": {
            "age": "28"
 }
 }
      ],
      "should": [
 {
          "match": {
            "firstname": "Winnie"
 }
 }
 ]
 }
 }
}

5.2.6 filter 过滤

不影响相关性得分,查询出满足 filter 条件的记录。

在 bool 中使用。

GET bank/_search
{
  "query": {
    "bool": {
      "filter": [
 {
          "range": {
            "age": {
              "gte":18,
              "lte":40
 }
 }
 }
 ]
 }
 }
}

5.2.7 term 查询

匹配某个属性的值。

全文检索字段用 match,其他非 text 字段匹配用 term

keyword:文本精确匹配 ( 全部匹配 )

match_phase:文本短语匹配

非 text 字段精确匹配
GET bank/_search
{
  "query": {
    "term": {
      "age": "20"
 }
 }
}

5.2.8 aggregations 聚合

聚合:从数据中分组和提取数据。类似于 SQL GROUP BY 和 SQL 聚合函数。

Elasticsearch 可以将命中结果和多个聚合结果同时返回。

聚合语法:

"aggregations" : {
    "<聚合名称 1>" : {
        "<聚合类型>" : {
            <聚合体内容>
        }
        [,"元数据" : {  [<meta_data_body>] }]?
        [,"aggregations" : { [<sub_aggregation>]+ }]?
    }
    [,"聚合名称 2>" : { ... }]*
}
  • 示例 1:搜索 address 中包含 big 的所有人的年龄分布 ( 前 10 条 ) 以及平均年龄,以及平均薪资
GET bank/_search
{
  "query": {
    "match": {
      "address": "mill"
 }
  },
  "aggs": {
    "ageAggr": {
      "terms": {
        "field": "age",
        "size": 10
       }
    },
    "ageAvg": {
      "avg": {
        "field": "age"
      }
    },
    "balanceAvg": {
      "avg": {
        "field": "balance"
      }
   }
 }
}

检索结果如下所示:

hits 记录返回了,三种聚合结果也返回了,平均年龄 34 随,平均薪资 25208.0,品骏年龄分布:38 岁的有 2 个,28 岁的有一个,32 岁的有一个

示例 1

如果不想返回 hits 结果,可以在最后面设置 size:0

GET bank/_search
{
  "query": {
    "match": {
      "address": "mill"
 }
  },
  "aggs": {
    "ageAggr": {
      "terms": {
        "field": "age",
        "size": 10
      }
    }
  },
  "size": 0
}
  • 示例 2:按照年龄聚合,并且查询这些年龄段的平均薪资

从结果可以看到 31 岁的有 61 个,平均薪资 28312.9,其他年龄的聚合结果类似。

示例 2

  • 示例 3:按照年龄分组,然后将分组后的结果按照性别分组,然后查询出这些分组后的平均薪资
GET bank/_search
{
  "query": {
    "match_all": {
 }
  },
  "aggs": {
    "ageAggr": {
      "terms": {
        "field": "age",
        "size": 10
      },
      "aggs": {
        "genderAggr": {
          "terms": {
            "field": "gender.keyword",
            "size": 10
          },
          "aggs": {
            "balanceAvg": {
              "avg": {
                "field": "balance"
          }
        }
      }
    }
  }
 }
  },
  "size": 0
}

从结果可以看到 31 岁的有 61 个。其中性别为 M 的 35 个,平均薪资 29565.6,性别为 F 的 26 个,平均薪资 26626.6。其他年龄的聚合结果类似。

聚合结果

5.2.9 Mapping 映射

Mapping 是用来定义一个文档 ( document ) ,以及它所包含的属性 ( field ) 是如何存储和索引的。
  • 定义哪些字符串属性应该被看做全文本属性 ( full text fields )
  • 定义哪些属性包含数字,日期或地理位置
  • 定义文档中的所有属性是否都能被索引 ( _all 配置 )
  • 日期的格式
  • 自定义映射规则来执行动态添加属性

Elasticsearch7 去掉 tpye 概念:

关系型数据库中两个数据库表示是独立的,即使他们里面有相同名称的列也不影响使用,但 ES 中不是这样的。elasticsearch 是基于 Lucence 开发的搜索引擎,而 ES 中不同 type 下名称相同的 field 最终在 Lucence 中的处理方式是一样的。

为了区分不同 type 下的同一名称的字段,Lucence 需要处理冲突,导致检索效率下降

ES7.x 版本:URL 中的 type 参数为可选。

ES8.x 版本:不支持 URL 中的 type 参数

所有类型可以参考文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html

  • 查询索引的映射

如查询 my-index 索引的映射

GET /my-index/_mapping
返回结果:
{
  "my-index" : {
    "mappings" : {
      "properties" : {
        "age" : {
          "type" : "integer"
        },
        "email" : {
          "type" : "keyword"
        },
        "employee-id" : {
          "type" : "keyword",
          "index" : false
        },
        "name" : {
          "type" : "text"
      }
    }
  }
 }
}
  • 创建索引并指定映射

如创建 my-index 索引,有三个字段 age,email,name,指定类型为 interge, keyword, text

PUT /my-index
{
  "mappings": {
    "properties": {
      "age": { "type": "integer" },
      "email": { "type": "keyword"  },
      "name": { "type": "text" }
    }
 }
返回结果:
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "my-index"
}
  • 添加新的字段映射

如在 my-index 索引里面添加 employ-id 字段,指定类型为 keyword

PUT /my-index/_mapping
{
  "properties": {
    "employee-id": {
      "type": "keyword",
      "index": false
    }
 }
}
  • 更新映射
我们不能更新已经存在的映射字段,必须创建新的索引进行数据迁移。
  • 数据迁移
POST _reindex
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter"
 }
}
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
23天前
|
SQL 存储 关系型数据库
美团面试:binlog、redo log、undo log的底层原理是什么?它们分别实现ACID的哪个特性?
老架构师尼恩在其读者交流群中分享了关于 MySQL 中 redo log、undo log 和 binlog 的面试题及其答案。这些问题涵盖了事务的 ACID 特性、日志的一致性问题、SQL 语句的执行流程等。尼恩详细解释了这些日志的作用、所在架构层级、日志形式、缓存机制以及写文件方式等内容。他还提供了多个面试题的详细解答,帮助读者系统化地掌握这些知识点,提升面试表现。此外,尼恩还推荐了《尼恩Java面试宝典PDF》和其他技术圣经系列PDF,帮助读者进一步巩固知识,实现“offer自由”。
美团面试:binlog、redo log、undo log的底层原理是什么?它们分别实现ACID的哪个特性?
|
30天前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1610 14
|
2月前
|
存储 缓存 关系型数据库
redo log 原理解析
redo log 原理解析
37 0
redo log 原理解析
|
2月前
|
设计模式 SQL 安全
PHP中的设计模式:单例模式的深入探索与实践在PHP的编程实践中,设计模式是解决常见软件设计问题的最佳实践。单例模式作为设计模式中的一种,确保一个类只有一个实例,并提供全局访问点,广泛应用于配置管理、日志记录和测试框架等场景。本文将深入探讨单例模式的原理、实现方式及其在PHP中的应用,帮助开发者更好地理解和运用这一设计模式。
在PHP开发中,单例模式通过确保类仅有一个实例并提供一个全局访问点,有效管理和访问共享资源。本文详细介绍了单例模式的概念、PHP实现方式及应用场景,并通过具体代码示例展示如何在PHP中实现单例模式以及如何在实际项目中正确使用它来优化代码结构和性能。
44 2
|
2月前
|
存储 关系型数据库 MySQL
binlog、redolog、undo log底层原理及ACID特性实现分享
在数据库管理系统中,日志机制是确保数据一致性、完整性和可靠性的关键组件。MySQL数据库中的binlog、redolog和undolog作为其核心日志系统,各自扮演着不同但同样重要的角色。本文将深入探讨这三种日志的底层原理以及它们如何分别实现ACID(原子性、一致性、隔离性、持久性)特性的不同方面。
55 0
|
3月前
|
消息中间件 监控 搜索推荐
OpenFeign日志组件Logger原理与应用
该文章详细解释了如何在OpenFeign中配置并使用请求和响应的GZIP压缩功能。
|
4月前
|
运维 中间件 数据库
浅析JAVA日志中的性能实践与原理解释问题之元信息打印会导致性能急剧下降问题如何解决
浅析JAVA日志中的性能实践与原理解释问题之元信息打印会导致性能急剧下降问题如何解决
|
3天前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
77 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
30天前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
182 3
|
25天前
|
Python
log日志学习
【10月更文挑战第9天】 python处理log打印模块log的使用和介绍
25 0