【ES系列】ES的数据结构与DSL语法

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

本篇章将围绕ES的基本功能、实现原理与性能优化这三个方面,使读者能够逐渐深入了解ES的特点与能力。本篇所用的版本为7.10.2同kibana版本,需要注意的是,es与kibana至少在大版本上要保持一致,否则功能上会有兼容性问题。

ES的特征

  1. 分布式:ES是分布式的开源搜索和分析引擎,基于Apache Lucene开发而成,适用于所有类型的数据,包括文字、数字、地理空间、结构化和非结构化数据
    1.1. 分布式架构:
    【ES系列】ES的数据结构与DSL语法
    之后的章节里,会逐步讲解ES的架构内容。

    1.2 集群(Cluster)
    1.3 节点(Node)
    1.4 副本(Replica):副本,replica主要用来保证高可用(故障转移)、数据备份、增强高吞吐的并行搜索
    1.5 分片(Shard):是非常重要的点,它允许ES跨分片(可以是多个节点)分布和并行操作,从而提高性能与吞吐量

  2. 存储方式:不同于数据库中的行列存储形式,ES将信息存储为JSON文档的数据结构

  3. 全文检索:全文检索功能是ES广泛运用的主要原因,由于分布式的特点,存储文档会分布整个集群中,因此搜索效率非常高

数据结构部分

ES通过倒排索引的数据结构做到快速索引和全文检索,该结构支持非常快速的全文本搜索。

一般情况下,ES默认对每个字段中的所有数据建立索引,并且每个索引字段都具备专有的优化数据结构
例如,文本字段是存储在倒排索引中,而数字或地理信息的字段存储在BKD树中,BKD树可以理解为多维度的树形结构。

数据类型 数据结构
text/keyword 倒排索引
数字/地理位置 BKD树

正向索引与倒排索引

定义

倒排索引的英文是Inverted index (link),是有转换的意思。被翻译成倒排我觉得有两个原因:

  1. 由于倒排索引不同于关系型数据库,通过id去查找内容,而在ES中是通过keyword,也就是文档内容去查找具体文件
  2. ES中还有个正排索引Forword Index表中记录文档中每个字的位置信息,查找时扫描表中每个文档中字的信息直到找出所有包含查询关键字的文档。

结构

下面针对两种索引举例(index_01: this is elasticsearch / index_02:elasticsearch query)

倒排索引

关键词 文档id
this index_01
is index_01
elasticsearch index_01, index_02
query index_02

正排索引

文档id 关键词
index_01 this, is, elasticsearch
index_02 elasticsearch, query

分词(keyword)

ES对于文档内容或者某一段文本,都会进行分词,也就是把一段话中的单词进行拆分。分词的效果将直接影响倒排索引的搜索能力。
所以选择合适的分词是十分重要的。对于不同语言,分词器也是不同的。比如英文会使用Standard, ngram等,中文可选ik分词器,常用有ik_smart_max_word。

这里以英文举例查看不同分词器的效果
在ngram_tokenizer的格式中,可以设置最大最小步长,

// An highlighted block
"tokenizer": {
	"my_tokenizer": {
	  "type": "ngram",
	  "min_gram": 1,
	  "max_gram": 2,
	  "token_chars": [
	    "letter",
	    "digit"
	  ]
	}
}

以"Qu Cdn"为例,使用ngram分词

// An highlighted block
{
  "tokenizer": "ngram",
  "text": "Qu Cdn"
}

以下是分词的返回结果,可以看到颗粒度限制在1-2的长度,甚至还包括空格

// An highlighted block
{
    "tokens": [
        {
            "token": "Q",
            "start_offset": 0,
            "end_offset": 1,
            "type": "word",
            "position": 0
        },
        {
            "token": "Qu",
            "start_offset": 0,
            "end_offset": 2,
            "type": "word",
            "position": 1
        },
        {
            "token": "u",
            "start_offset": 1,
            "end_offset": 2,
            "type": "word",
            "position": 2
        },
        {
            "token": "u ",
            "start_offset": 1,
            "end_offset": 3,
            "type": "word",
            "position": 3
        },
        {
            "token": " ",
            "start_offset": 2,
            "end_offset": 3,
            "type": "word",
            "position": 4
        },
        {
            "token": " C",
            "start_offset": 2,
            "end_offset": 4,
            "type": "word",
            "position": 5
        },
        {
            "token": "C",
            "start_offset": 3,
            "end_offset": 4,
            "type": "word",
            "position": 6
        },
        {
            "token": "Cd",
            "start_offset": 3,
            "end_offset": 5,
            "type": "word",
            "position": 7
        },
        {
            "token": "d",
            "start_offset": 4,
            "end_offset": 5,
            "type": "word",
            "position": 8
        },
        {
            "token": "dn",
            "start_offset": 4,
            "end_offset": 6,
            "type": "word",
            "position": 9
        },
        {
            "token": "n",
            "start_offset": 5,
            "end_offset": 6,
            "type": "word",
            "position": 10
        }
    ]
}

使用Standard分词情况,返回的结果就是按空格分开

// An highlighted block
{
    "tokens": [
        {
            "token": "Qu",
            "start_offset": 0,
            "end_offset": 2,
            "type": "<ALPHANUM>",
            "position": 0
        },
        {
            "token": "Cdn",
            "start_offset": 3,
            "end_offset": 6,
            "type": "<ALPHANUM>",
            "position": 1
        }
    ]
}

分词器的不同,ES创建的倒排索引结构也将不同,进而编写的搜索条件也将不同。
这里需要考虑的是,分词器的分词颗粒度越细,倒排索引的结构也就越大。之后就是匹配度与性能的鱼和熊掌的问题。

所以要根据实际业务选择合适的分词器,下一部分将展示不同的elasticsearch-dsl语句。

DSL语句

同其他类型的数据库一样,ES也有自己的query语言,其搜索结构都是由json串组合构成请求体发送。

常用DSL语句

索引部分

创建索引

创建索引最关键的部分就是settings跟mappings的部分,settings设置包括分片副本,分词器等内容
mappings就是index所包含的映射结构与内容,比如mappings中可以是否为动态映射。

PUT /index03
{
  "settings": {
    "analysis": {
        "analyzer": {
            "ngram_analyzer": {
                "tokenizer": "ngram_tokenizer",
                "filter": ["lowercase"]
            }
        },
        "tokenizer": {
            "ngram_tokenizer": {
                "type": "ngram",
                "min_gram": 3,
                "max_gram": 3
            }
        }
    },
  "mappings":{
  	"dynamic": false,
  	"properties":{
		"object":{
			"attr":{
				"name": {"type": "keyword"},
                "site": {"type": "long"},
                "filepath": {"type": "text"},
                "filename": {"type": "keyword"},
                "date": {"type": "keyword"}
			}
		}
	}
  }
  }
}

需要注意的是,如果一个index中field太多会导致映射爆炸的问题,所以需要设定index.mapping.total_fileds_limit属性

查看es所有索引
GET /_cat/indices?v 

【ES系列】ES的数据结构与DSL语法

查看单个索引
GET /index03
删除索引
DELETE /index03

文档部分

创建文档
POST /index03/_doc/7
{
  "name" : "kibana",
  "site" : 212121,
  "date" : "20230101",
  "filepath" : "/a/b/k/d/e/f",
  "filename" : "nothing"
}
批量执行
POST /index03/_doc/_bulk
{"index":{"_id":7}}
{"name":"elastic","site":24,"filepath":"/a/b/k/d/e/f"}
{"index":{"_id":8}}
{"name":"search","site":-11,"filepath":"/a/b/k/d/e/f"}
{"index":{"_id":9}}
{"name":"stack","site":0,"filepath":"/a/b/k/d/e/f"}
查询文档
GET /index03/_doc/7

返回值

{
  "_index" : "index03",
  "_type" : "_doc",
  "_id" : "7",
  "_version" : 1,
  "_seq_no" : 6,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "kibana",
    "site" : 212121,
    "date" : "20230101",
    "filepath" : "/a/b/k/d/e/f",
    "filename" : "nothing"
  }
}

查询操作DSL

DSL Query的分类
Elasticsearch提供了基于JSON的DSL(Domain Specific Language)来定义查询。常见的查询类型包括:

查询所有:查询出所有数据,一般测试用。例如:match_all

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

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

地理(geo)查询:根据经纬度查询。例如:
geo_distance, geo_bounding_box

复合(compound)查询:复合查询可以将上述各种查询条件组合起来,合并查询条件。例如:
bool, function_score

查询验证

这是比较重要的一个点,有些时候语句执行出错,需要排查是数据问题,还是搜索语法的问题。
比如我这里举例在文档里找indexname为killbill的数据,但实际没有indexname这个field(类似mysql的column)

GET /index03/_doc/_validate/query?explain
{
  "query":{
    "match":{
      "indexname":"killbill"
    }
  }
}

如果语法是正确的话,会返回

{
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  },
  "valid" : true,
  "explanations" : [
    {
      "index" : "index03",
      "valid" : true,
      "explanation" : """+MatchNoDocsQuery("unmapped fields [indexname]") #*:*"""
    }
  ]
}

这里显示语法检查是正确的,并且会提示mappings里面没有indexname这个field
是一个非常好用的语法

条件查询

这里主要介绍几种查询的语法格式,相同语法格式会合并,就是替换关键词就行。比如match可以换成match_phrase,语法格式上没有区别,只是query下的搜索关键词不同。

match/match_phrase(完全匹配)

match:分词后搜索。比如分词后有N个分词,只要匹配上其中一个就可以返回数据了
match_phrase:分词后搜索。与match不同的是,match_phase分出来的词必须全部在搜索结果中,且位置顺序是一样的。

GET /index03/_doc/_search
{
  "query":{
    "match":{
      "name":"AFIND"
    }
  }
}
match_all并且排序
GET /index03/_search
{
    "query":{
        "match_all":{}
    },
    "sort":{
        "site":{
            "order":"desc"
        }
    }
}
多条件查询
GET /index03/_search
{
    "query":{
        "bool":{ # 表示需要进行条件过滤
            "must":[{ #表示必须满足下面的条件,并且参与计算分值,常用的子句还有should,表示“或”的意思
                "wildcard":{
                    "filename":"*bill"
                }
            },{
                "match":{
                    "site": 10086
                }
            }]
        }
    }
}
聚合分页查询

需要注意的是,在聚合中,只能针对整型类的数据类型(byte,short,integer,long)

GET /index03/_search
{
    "aggs":{ #表示聚合操作
        "site_group":{ #聚合后分组名称,可以随便起
            "terms":{ #表示分组操作,也可以使用avg来求平均值
                "field":"site" #表示对哪一个字段进行分组
            }
        }
    },
   "size":0 #表示不查询原始数据,只查询分组结果
}

结语

本篇内容主要介绍了ES的入门知识点与常用操作的语法,之后会基于其内核Lucene以及分布式架构展开并且深入,并设计性能提升方案。文章来源地址https://www.toymoban.com/news/detail-464869.html

到了这里,关于【ES系列】ES的数据结构与DSL语法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • ES高级查询语法DSL实战 - 第504篇

    历史文章( 文章 累计500+) 《国内最全的Spring Boot系列之一》 《国内最全的Spring Boot系列之二》 《国内最全的Spring Boot系列之三》 《国内最全的Spring Boot系列之四》 《国内最全的Spring Boot系列之五》 《国内最全的Spring Boot系列之六》 《国内最全的Spring Boot系列之七》 E

    2024年04月27日
    浏览(37)
  • 【ES专题】ElasticSearch 高级查询语法Query DSL实战

    个人在学习的过程中,感觉比较吃力的地方有如下: 语法结构比较陌生 没有中文文档, 只能看英文 其他博客也比较少介绍语法结构。比如说,为什么查询中会出现 query 有ES入门基础,且想进一步学习ES基本操作的朋友 系列上一篇文章:《【ES专题】ElasticSearch快速入

    2024年02月06日
    浏览(36)
  • 一文掌握系列之Es的DSL查询操作

    ES在查询的时候非常方便, 笔者总结了Es的基础查询操作,供大家指正和学习。 match_all 全部查询,配合其他的操作进行数据的筛选,字段的筛选等,并且伴随着条件的增加,建议使用POST方式, 筛选字段 _source对需要的字段进行筛选。 分页 from a size b 拿到目的集合中索引为

    2023年04月12日
    浏览(26)
  • Elasticsearch数据结构与查询语法

    Elasticsearch是一个基于Lucene的搜索引擎,它提供了实时、可扩展、可伸缩的搜索功能。Elasticsearch是一个分布式、实时的、多用户的搜索和分析引擎。它是基于Lucene的搜索引擎,用于实时、可扩展、可伸缩的搜索功能。Elasticsearch是一个分布式、实时的、多用户的搜索和分析引擎

    2024年02月21日
    浏览(31)
  • ES6: Map数据结构

    概念: 类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。 初识Map 实例的属性和方法 size:返回 Map 结构的成员总数。 Map.prototype.set(key,value) :添加key对应的value,返回 Map 结构本身。 Map.prototype.get(key) :获取key对应的

    2024年02月16日
    浏览(28)
  • ES6 Map数据结构

    ES6 提供的另一种新的引用类型的数据结构 它类似于对象,也是键值对的集合,但是 “键”的范围不限于字符串 ,各种类型的值(包括对象)都可以当作键) 以前引用类型中的 对象也是键值对的集合 但是键限于字符串 总结起来就是: Object 结构提供了“字符串—值”的对

    2024年02月07日
    浏览(31)
  • ES核心干货学习(原理及数据结构)

    ES是建立在Lucene基础之上的分布式准实时搜索引擎。 核心:分布式和Lucene全文搜索。 1.2 什么场景需要用ES 1. 业务需要进行大量数据实时检索时,传统关系型数据库无法支撑。 2. 需要进行分词检索,语义检索 3. 需要大数据分析 符合上面特征都可以考虑,如日志收集、订单数

    2024年02月15日
    浏览(31)
  • Java完整版(JavaSe语法,数据结构,Mysql,网络,JavaWeb, 测试)

    1.JavaSe语法: JavaSe要点速记 2.数据结构: 6.1(Java)(顺序表) 6.2.1(Java)(无头不循环单链表) 6.2.2(Java)(无头不循环双链表) 6.3(Java)(栈) 6.4(Java)(队列) 6.5(Java)(二叉树) 6.6(Java)(堆) 6.7(Java)(排序) 6.8(Java)(Map和Set) 6.9(Java)二叉搜索树 3.数据库: mysql数据库 4.JavaWeb:   8.Java多线程 java文件

    2024年02月04日
    浏览(28)
  • es的数据存储结构;近实时查询原因

    es 存储中大体可以看成 index(表) + document(行记录) 组成 es 支持分布式存储,一个 index 会产生多个分片,保存在不同的实例上。其中分为 若干个主分片 和 副分片 。当主分片挂了,会切换到副分片,主分片和副分片的数据是一致的(写的时候先找主分片,读的时候是2者都可

    2024年02月09日
    浏览(27)
  • JavaScript(ES6)数据结构与算法之树

    6.1 概念 非线性结构 n(n=0)个节点构成的有限集合,n=0时称为空树 对于任一非空树 有一个根节点 其余节点可以构成子树 树的术语: 节点的度 :节点的子树个数 树的度 :树所有节点中最大的度数 叶节点 /叶子节点:度为零的节点 父节点:有子树的的节点是子树根节点的父节

    2024年02月04日
    浏览(28)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包