ES入门指南

这篇具有很好参考价值的文章主要介绍了ES入门指南。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

  1. 本文章适用于未接触ES或接触较少的中高级开发工程师,以较低的学习成本,快速学习ES并在生产中应用为核心目的

  2. 本文章主要以实战维度展开,在不影响数据安全以及基本的性能危机的前提下,不会过多的涉及深层次的底层原理(但也会涉及一些基本的原理,防止出现类似功能分辨不清导致系统性能受到极大的损耗的生产事故)

  3. 本文章借鉴了多个ES相关文档以及书籍《ES权威指南》,同时也进行了很多加工处理,例如: 横向DB对比、生涩知识点拆解为更通俗易懂的语言、以实战为主的知识点汇总、使用不当导致的风险点预知、涉及的编程思想等。希望能对大家在ES的学习上起到一定帮助。

环境

  1. jdk - v1.8

  2. ES - v7.x

目录

  1. 使用场景

  2. 存储结构

  3. 常用语句

  4. API

  5. 索引

  6. 映射

  7. 更新

  8. 查询

  9. API查询

  10. DSL查询

使用场景

  1. 数据库ES、Mysql、Mongo等,核心是围绕CRUD。其中各DB的核心特性又取决于其存储结构。这里通过类比的方式来阐述ES的使用场景

  2. Mysql核心存储结构是B+树,擅长范围查询(因B+树数据存储在叶子节点并用链表的方式相互关联,有利于做范围类查询操作)

  3. Mongo核心存储结构是B树,擅长单数据查询(因B树任意节点都可以存储数据,这样在根据条件查询一条数据时,就会比mysql的随机IO次数平均值小)

  4. ES核心存储结构是倒排索引(倒排索引原理后续会讲到),由于是属于重度空间换时间结构,所以在合理使用的前提下(这里特指结构化查询和过滤),范围、单数据等查询都具有不错的性能表现,但是相对的更新数据成本会更高。

  5. 综上所述,ES更适合写少读多的场景。并且对各种复杂查询都有良好的支持。

存储结构

  1. ES使用的是倒排索引,和正排索引通过key查询value不同,倒排索引是通过value反向查询key。

  2. 例如,当进行关键词查询时,如果是正向索引需要扫描索引库中的所有文档,找到所有包含关键词的文档。很显然这样性能会成为问题。而倒排索引则是根据关键词去寻找对应文档。每个关键词都对应这一系列文档,这样只要建立了该关键词的索引,就可以避免全索引库扫描的方式来进行关键词查询。

  3. 那么ES又是如何生成索引的呢,举个例子,这里有两个文档,1: “小红明天去上学”,2: “小白明天不去上学”,这时ES在添加数据时,会进行分词从而得到“小红”、“小白”、“明天”、“明天”、“去”、“不去”、“上学”,“上学”各词组。然后我们会发现,有2个明天和2个上学。那么这个时候ES会将各词组当作索引项,对应的是该词组出现的文档,例如:

小红: 文档1

小白: 文档2

明天: 文档1、文档2

...

这样就生成了倒排索引,这种索引结构,在2例的场景下可以极大的提高搜索性能。

常用语句(基于kibana)

API

  1. Java Api

  2. 基于HTTP协议,以JSON为数据交互格式的RESTful API

索引(index)

  1. ES中的索引(index)类比关系型数据库中table的概念(5.0版本是以type对应关系型数据库 table的概念,7.0后取消了多type概念,最多一个,建立index时如果不设置会默认创建一个type且最多一个type)

  2. 建立索引: PUT /{index_name} (不可以有大写)

映射(mapping)

  1. ES中的映射能力主要是为了给字段设定类型。虽然ES可以在索引有新字段的文档时会自动基于json类型规则生成映射,但是为了防止查询混乱的情况,我们一般会选择手动建立映射。例如: 当索引一个带有引号的数字”22”,这时他将会被映射为string类型。如果这时字段已经被映射为long类型,es将会尝试转换字符串为long,并在失败时会抛出异常。

  2. 建立映射语句:

      PUT /{index_name}
      {
        "mappings": {
          "properties": {
            "name": {
              "type": "text"
            },
            "age": {
              "type": "integer"
            }
          }
        }
      }
  字段释义:
    mappings, 映射
    properties, 特性定义
    type, 字段类型

  PS: 此处还可设置分词器插件等相关属性

更新

添加文档: POST

_index、_type、_id三者唯一确定一个文档,所以想要保证文档是新加入的,最简单的方式是使用POST方法让ES自动生成唯一_id(type 7.0后默认为_doc)

         POST /{index_name}/_doc
         {
           "studentName": "小明",
           "age": 22
         }

如果想自定义ID则可以使用_create关键字(只有在index+type+id均不存在时才会执行成功)

         PUT /{index_name}/_doc/{id}/_create
         {
           "studentName": "小红",
           "age": 22
         }
  1. 更新文档:

全局更新: PUT, 在ES中,文档不能通常意义上的局部修改,只可以通过重建索引或者替换来实现文档更新,实现过程如下:

  1. 从旧文档中检索JSON

  2. 修改它

  3. 删除旧文档

  4. 索引新文档

         PUT /{index_name}/_doc/{id}
         {
           "studentName": "小白",
           "age": 12
         }

局部更新: POST, 在使用层次ES提供了局部更新的能力,但是在ES内部中,依然遵循着上述的四个步骤,不过即便是这样,也一定程度上节约了网络IO和解决了并发问题(换句话说可以理解为ES将局部更新做了原子化处理)。因为如果没有这个能力,我们想要实现局部更新就不得不先将文档查询出来,然后将修改好的数据再通过PUT API请求发送到ES。

         POST /user/_doc/1/_update
         {
           "doc": {
             "name": "李四"
           }
         }
         PS: doc为type值,由于7.0后取消了多type机制,所以当没有设置type时,这里默认为doc

查询

HTTP查询语句部分:

根据索引名称、类型和文档ID查询:

GET /{index_name}/_doc/{id}

1. index_name: 索引名称
2. type: 类型(7.0版本后与index_name为1对1关系)
3. id: 文档id

查询一个索引下的所有数据:

GET /{index_name}/_doc/_search
PS: _search:标记为查询操作的关键字,添加此关键字后,可进行更细粒度的查询操作。

条件查询

在请求中依旧使用 _search 关键字,然后将查询语句传递给参数 q= 。这样就可以得到所有field_name为field_value的结果.

GET /{index_name}/_doc/_search?q={field_name}:{field_value}

结构化查询和结构化过滤(DSL语句):

  1. 结构化查询:查询能力更强,具有相关性分析能力,整体查询原理更为动态,但是因为会实时计算相关性、分析等行为,无法进行缓存操作,导致性能相对较慢

  2. 结构化过滤:进行精确相等性匹配过滤然后存入内存,因为是完全基于索引并且使用了缓存,所以在大量级场景下具有稳定的性能。

  3. 使用建议:原则上来说,使用查询语句做全文本搜索或其他需要进行相关性评分的时候,剩下的全部用过滤语句

常用查询语句和过滤语句:

query: _search关键字中DSL语句最外层关键字,且_search下只能有query

         GET /{index_name}/_doc/_search
         {
           "query":{
             ...
           }
         }

term - 过滤类语句:主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed 的字符串(未经分析的文本数据类型)

         GET /{index_name}/_doc/_search
         {
           "query":{
             {
               "term": {
                 "age": 26
               }
             }
           }
         }

terms - 过滤类语句: terms 跟 term 有点类似,但 terms 允许指定多个匹配条件。 如果某个字段指定了多个值,那么文档需要一起去做匹配:

         GET /{index_name}/_doc/_search
         {
           "query": {
             "terms": {
               "age":[26, 33]
             }
           }
         }

range - 过滤类语句: 允许我们按照指定范围查找一批数据

         GET /{index_name}/_doc/_search
         {
           "query": {
              "range": {
                "age": {
                  "gte": 20,
                  "lt": 30
                }
              }
           }
         }
         PS:范围操作符包含: 
         gt: 大于
         gte: 大于等于
         lt: 小于
         lte: 小于等于

exists 和 missing - 过滤类语句: 可以用于查找文档中是否包含指定字段或没有某个字段,类似于SQL语句中的 IS_NULL 条件

         GET /{index_name}/_doc/_search
         {
           "query": {
             "exists": {
               "field": "name"
             }
           }
         }
         PS: 这两个过滤只是针对已经查出一批数据来,但是想区分出某个字段是否存在的时候使用。

bool - 过滤类语句: 过滤可以用来合并多个过滤条件查询结果的布尔逻辑,它包含以下操作符:

1. must:多个查询条件的完全匹配,相当于 and

2. must_not:多个查询条件的相反匹配,相当于 not 。

3. should:至少有一个查询条件匹配, 相当于 or 。

         GET /{index_name}/_doc/_search
         {
           "query": {
             "bool": {
               "must": {"term": {"studentName": "张三"}},
               "nust_not": {"term": {"age": 22}},
               "should": [
                 {"term": {"hasMan": true}},
                 {"term": {"hasMonitor": false}}
               ]
             }
           }
         }

match_all - 查询类语句: 可以查询到所有文档,是没有查询条件下的默认语句

GET /{index_name}/_doc/_search
{
  "query": {
    "match_all": {
      
    }
  }
}

match - 查询类语句: 匹配查询,全文(Fulltext)查询

不同于词条查询ES在处理全文查询时,会先对查询条件进行分析,然后根据分词插件做分词处理,最终以分词结果进行查询并返回查询结果。例如:

{
  "query": {
    "match": {
      "msg": "Hello world"
    }
  }
}

如上所述, 在执行"hello world"查询条件时,会先进行分析器进行分词得到小写的hello和world,然后默认会执行字段“msg”的值,在hello和world中包含任意一个,则返回的逻辑。当然,这个是“or”逻辑就也可以设置为“and”逻辑。

PS: 此处包含有三种类型的匹配查询(默认为布尔,上述就是布尔匹配查询类型的运行逻辑,由于此处展开讲内容量较大,涉及较多机制设定、原理等问题,入门指南不做讲解,后续进阶系列会详细描述):

布尔

短语

短语前缀

PS:需要注意的是,如果是做精确查询,因为过滤类语句会进行缓存,所以最好使用过滤类语句。

multi_match - 查询类语句: 允许你做 match 查询的基础上同时搜索多个字段

         {
           "query": {
             "multi_match": {
               "query": "123",
               "fields": [
                 "name",
                 "age"
               ]
             }
           }
         }

bool - 查询类语句: bool 查询与 bool 过滤相似,用于合并多个查询子句。不同的是, bool 过滤可以直接给出是否匹配成功, 而 bool 查询 要计算每一个查询子句的 _score (相关性分值)。(此处摘自: ES权威指南)

1. must:查询指定文档一定要被包含。

2. must_not:查询指定文档一定不要被包含。

3. should:查询指定文档,有则可以为文档相关性加分。

4. 以下查询将会找到 title 字段中包含 "how to make millions",并且 "tag" 字段没有被标为 spam。如果有标识为 "starred",或者发布日期为2014年之前,那么这些匹配的文档将比同类网站等级高

{
  "bool": {
    "must": {
      "match": {
        "title": "how to make millions"
      }
    },
    "must_not": {
      "match": {
        "tag": "spam"
      }
    },
    "should": [
      {
        "match": {
          "tag": "starred"
        }
      },
      {
        "range": {
          "date": {
            "gte": "2014-01-01"
          }
        }
      }
    ]
  }
}
PS: 如果 bool 查询下没有 must 子句,那至少应该有一个 should 子句。但是 如果有 must 子句,那么没 有 should 子句也可以进行查询。

查询与过滤条件的合并:

因为search API中只能包含query语句,所以我们需要用filtered来同时包含query和filter子句:文章来源地址https://www.toymoban.com/news/detail-402067.html

GET /{index_name}/_doc/_search
{
  "query": {
    "filtered": {
      "query": {
        "match": {
          "email": "business opportunity"
        }
      },
      "filter": {
        "term": {
          "folder": "inbox"
        }
      }
    }
  }
}
PS: 在混合使用时需要注意的是,我们很少用到的过滤语句中包含查询,保留这种用法只是为了语法的完整性。 只有在过滤中用到全文本匹配的时候才会使用这种结构。

到了这里,关于ES入门指南的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 谷歌 Bard上线正面挑战ChatGPT,基于精简版的LaMDA需要更少的计算能力来接触更多的用户并获得更多的反馈

    虽然有关 Bing 上集成ChatGPT的泄密和谣言在网上层出不穷,但谷歌在 Big G 举办的活动前两天让所有人大吃一惊,这里宣布了Bard的到来。就在几天前,谷歌还承诺,其产品使用的 AI 只是尝鲜,很快就会看到一些消息。2 月 6 日晚抵达,Alphabet通过首席执行官桑达尔·皮采 (Sundar

    2024年02月13日
    浏览(41)
  • 数据结构入门指南:链表(新手避坑指南)

    目录 前言 1.链表 1.1链表的概念  1.2链表的分类 1.2.1单向或双向 1.2.2.带头或者不带头 1.2.33. 循环或者非循环 1.3链表的实现  定义链表 总结         前边我们学习了顺序表,顺序表是数据结构中最简单的一种线性数据结构,今天我们来学习链表,难度相较于顺序表会大幅增

    2024年02月15日
    浏览(56)
  • rabbitMQ入门指南:管理页面全面指南及实战操作

      在前一篇文章在centos stream 9环境中部署和使用rabbitMQ,我们已经详细介绍了如何在CentOS下安装和配置RabbitMQ,我们不仅启动了RabbitMQ服务,还通过插件安装了管理后台,并且登陆到管理页面。   RabbitMQ管理后台提供了一个直观的用户界面,允许我们查看和管理RabbitMQ服务器

    2024年02月12日
    浏览(50)
  • HarmonyOS云开发基础认证题目记录——包括第一期:Serverless基础、第二期:快速构建用户认证系统、第三期:云函数入门指南、第四期:云数据库入门指南、第五期:云存储入门指南。

    1. 【判断题】  应用架构的演进依次经历了微服务架构、单体架构、Serverless架构等阶段。 错误 2. 【判断题】  认证服务手机号码登录需要填写国家码。 正确 3. 【判断题】  认证服务在绑定微信账号后就不能再绑定QQ账号了。 错误 4. 【判断题】  云函数可以根据函数的实际

    2024年02月05日
    浏览(117)
  • (入门向)面向萌新的算法比赛入门指南

    算法是指解决问题或完成特定任务的一系列明确指令或步骤集合。它是一个定义良好、逐步执行的操作序列,用于将输入转换为输出。算法可用于计算、数据处理、自动化控制、问题解决等各个领域。 算法通常由一系列简单的操作组成,这些操作可以是基本的数学运算、逻辑

    2024年02月07日
    浏览(50)
  • Oracle 基础入门指南

      Oracle是一款由美国Oracle公司开发的关系型数据库管理系统。它支持SQL查询语言,并提供了丰富的功能和工具,用于管理大规模数据存储、处理和访问。Oracle被广泛应用于企业级应用中,包括金融、电信、零售等各行各业。 要开始学习Oracle,首先需要在计算机上安装Oracle数据

    2024年02月19日
    浏览(38)
  • RabbitMQ入门指南

    提供了系统之间的异步调用,比如一个支付功能,用户在支付完成之后,会去数据库中执行后续操作,然后更新支付状态,会生成订单信息,如果后续还需要添加功能,就需要去业务逻辑中修改代码,这样就会出现业务耦合。同时想要执行后续操作,需要等待支付功能完成,

    2024年02月21日
    浏览(80)
  • 领域驱动设计入门指南

    ​ 领域驱动设计(Domain-Driven Design,简称DDD)是一种软件架构风格,它强调在软件开发过程中紧密关注业务需求和领域知识。本文将简要介绍领域驱动设计的核心概念,帮助人开始学习和实践领域驱动设计。 什么是领域驱动设计? 领域驱动设计是一种软件开发方法,它侧重

    2024年02月11日
    浏览(37)
  • Go 语言入门指南

    学一门语言先看看helloworld吧,感觉go结合了好多语言的方式,写起来一会像python一会像c++,java差不多。反正语法挺奇特 go语言特点: 高性能、高并发 语法简单,学习曲线平缓 丰富的标准库 完善的工具链 静态链接 快速编译 跨平台 垃圾回收 首先听到老师说 go语言编译贼快,

    2024年02月15日
    浏览(45)
  • HTML 入门指南

    参考:HTML 教程- (HTML5 标准) HTML:超级文本标记语言(HyperText Markup Language) “超文本” 就是指页面内可以包含图片、链接等非文字内容。 “标记” 就是使用标签的方法将需要的内容包括起来。例如: a herf=\\\"sfdsfsd\\\"www.itcast.cn/a img/ HTML 用于 编写网页 。平时上网通过浏览器看到

    2024年02月20日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包