前言:
Elasticsearch(ES)是什么
Elasticsearch是一个基于Lucene构建的开源、分布式、RESTful接口全文搜索引擎。ES还是一个分布式文档数据库,其中每个字段均是被索引的数据且可以被搜索,它可以扩展至数以百计的服务器存储以及处理PB级别的数据。它可以在很短的时间内存储、搜索和分析大量的数据。它通常作为具有负责搜索常见情况下的核心发动机。
优点
-
横向扩展性:只需要增加一台机器,做一点配置,启动一下es进程就可以并入集群
-
分片机制提供更好的分布性:同一个索引可以分成多个分片(shard);分而治之的方式可以提高处理效率
-
高可用性(repica机制):提供replica机制,一个分片可以设置多个replica,使得某台服务器在宕机的情况下,集群依旧可以正常运行,并会把服务器宕机丢失的数据信息复制恢复到其他可用node上
-
使用简单:只需要一条命令就可以下载文件,然后很快就可以搭建一个站内搜索引擎
Lucene倒排索引
倒排索引引源于实际应用中需要根据属性的值来查找记录。这种索引表中的每一项都包括一个属性值和具有该属性值的各记录地址。由于不是由记录来确定属性值,而且由属性值来确定记录的位置,所以被称为倒排索引。
建立倒排索引的步骤:
-
取得关键词:实际上就是讲文本都拆成关键词的形式
-
建立倒排索引
例如,我们有两个文档,每个文档content字段包含:
-
The quick brown fox jumped over the lazy dog
-
Quick brown foxes leap over lazy dogs in summer
为了创建倒排索引,我们首先切分每个文档的content字段为单独的单词(我们把它们叫做词(terms)或者表征(tokens))(译者注:关于terms和tokens的翻译比较生硬,只需知道语句分词后的个体叫做这两个。),把所有的唯一词放入列表并排序,结果是这个样子的:
关键词
文章号【出现频率】
出现位置
brown
1[1]
3,2
dogs
1
9
1、关键字是按照字符串顺序排列的(Lucene没有使用b树结构,使用的是Finite State Transducers 简称 FST, 中文名:有穷状态转换器。),可以使用二分法快速定位关键词
2、实现时,Lucene将上面三列分别作为词典文件、频率文件、位置文件保存。需要特别指出,词典文件不仅仅是保存了每个关键词,还保留了指向频率文件和位置文件的指针,通过指针可以找到该关键字的频率信息和位置信息
补充:
为了减少索引文件大小,Lucene对索引使用了压缩技术
-
一、索引
索引
1、概念介绍
索引是具有相同结果的文档集合。
索引分析:首先将一个文本块分析成一个个单独的词(term),为后面的倒排索引做准备。然后标准化这些词为标准形式,提高他们的”可搜索性“。这些工作是分析器完成的。一个分析器(analyzers)是一个组合,用于将三个功能放到一起:
字符过滤器:字符串经过字符过滤器处理,他们的工作是在标记化之前的处理字符串。字符串可以去除html标记,或者转换&为and
分词器:分词器被标记化成独立的词。一个简单的分词器可以根据空格或逗号将单词分开。
标记过滤器:每个词都通过所以标记过滤处理,他可以通过修改词,去掉词,或者增加词。
2、索引管理
-
创建索引
代码块
PUT oplog
{
"settings" : {
"index" : {
"number_of_shards" : 3,
"number_of_replicas" : 2
}
},
"mappings" : {
"product_oplog":{
"properties" : {
"diff" : { "type" : "text" }
}
}
}
}
创建了一个名为oplog的index
返回的结果:
-
删除索引
代码块
DELETE oplog
删除secislan这个索引
返回的结果:
-
获取索引
代码块
GET oplog
获取oplog(会将索引的信息都显示出来包括一些默认的配置)
返回的结果:
操作es打印的log:
3、索引映射管理
-
增加映射
实际上就是向index添加文档类型(type),或者向文档类型中添加字段(field)
代码块
PUT /oplog/_mapping/product_oplog
{
"product_oplog":{
"properties" : {
"extend" : { "type" : "text" }
}
}
}
返回的结果:
4、索引别名
-
增加别名
代码块
PUT /oplog/_alias/my_index
结果:
-
删除别名
代码块
PUT /oplog/_alias/my_index
结果:
-
删除别名
代码块
POST /_aliases
{
"actions":[
{"remove": {"index": "oplog", "alias": "my_index"}}
]
}
索引别名一旦创建无法修改,只能先remove然后重新add
5、分词器
-
standard 分词器:默认分词器,会将词汇单元转成小写形式并且去除停用词和标点符号,支持中文采用的方法为单字切分。
-
simple分词器:首先会通过非字母字符来分割文本信息,然后将词汇单元统一为小写形式。该分词器会去除掉数字类型的字符。
-
ik分词器:支持两种分词模式,ik_max_word: 会将文本做最细粒度的拆分,会穷尽各种可能的组合;ik_smart: 会做最粗粒度的拆分
-
文档管理
文档是具体的数据,一个文档有点类似于数据库中的一行记录,文档必须包含在一个索引中。且文档的格式是json格式。
1、自动创建索引
当创建文档的时候,如果索引不存在,则会自动创建该索引。自动创建的索引会自动映射每个字段的类型。
2、自动创建ID
当创建文档的时候,如果不指定ID,系统会自动创建ID
3、分片的选择
默认情况下,分片的选择是通过ID的散列值进行控制的。这个只可以通过router参数进行手动控制
文档基本操作
创建文档
代码块
PUT /oplog/product_oplog/123
{
"diff":"hello world",
"extend":"hello everyone"
}
获取文档
代码块
GET /oplog/product_oplog/123
返回结果:
二、映射
1、映射
映射是定义存储和索引的文档类型以及字段的过程。索引的每一个文档都有一个类型,每种类型都有它自己的映射。一个映射定义了文档结构内每个字段的数据类型。映射通过配置来定义字段类型与该类型相关联的元数据的关系。
映射实例:
_id字段:每个被索引的文档都会关联_type字段和一个_id字段。_id字段没有索引,它的值可以从_uid字段自动生成
_index字段:_index字段可以匹配到包含某个文档的索引。该字段是一个虚拟字段,不作为一个真实的字段添加到Lucene索引中。这意味着可以在term或者terms查询中使用_index字段
_source字段:包含索引时原始的json文档内容,字段本身不建立索引,但是会被存储,所以在执行获取请求的时候可以返回source字段。
_type:每个索引的文档都包含_type和_id字段,索引_type字段的目的是通过类型名加快搜索进度
2、字段数据类型
代码块
核心数据类型
字符串数据类型:string//es 5.0后取消了string类型,由text和keyword替代(text 数据类型被用来索引长文本,比如说电子邮件的主体部分或者一款产品的介绍;keyword类型适用于索引结构化的字段,比如email地址、主机名、状态码和标签)
数字数据类型:long、integer、short、byte、double、float
日期类型:date
布尔类型:boolean
二进制数据类型:binary
复杂数据类型
对象数据类型:object
嵌套数据类型:nested
3、映射参数
analyzer参数:
可分词的字符串类型字段的值通过一个分析器将字符串转换为一连串的索引词。例如,字符串”THe quick foxes“,取决于使用的分词器,可能被分词为”The,quick ,fox,"。这些是字段创建索引时的实际索引词,可以试大段文本中的特定单词的搜索更加高效。分析的过程不仅发生在索引阶段,也可以发生在查询阶段:查询字符串需要通过相同的分析器进行分析。所以,查询中的索引词和索引中索引词具有相同的格式。
4、动态映射
设置dynamic字段
在es中可以不事先建好索引结构,在使用的时候可以直接插入文档到索引中,系统会根据文档的内容字段进行索引结构的动态映射,这样就极大的简化了索引的操作。
三、搜索
1、结构化查询
精确查询:
代码块
GET /oplog/product_oplog/_search
{
"query" : {
"constant_score" : {
"filter" : {
"term": {
"extend": "hello"
}
}
}
}
}
返回结果:
constant_score 将 term 查询转化成为过滤器
组合查询:
代码块
GET /oplog/product_oplog/_search
{
"query" : {
"constant_score" : {
"filter" : {
"bool":{
"should":[
{"term":{"diff":"hello"}}
],
"must_not":{
"term":{"extend":"hell"}
}
}
}
}
}
}
返回结果:
must
所有的语句都 必须(must) 匹配,与 AND 等价。
must_not
所有的语句都 不能(must not) 匹配,与 NOT 等价。
should
至少有一个语句要匹配,与 OR 等价。
查找多个精确值:
代码块
GET /oplog/product_oplog/_search
{
"query" : {
"constant_score" : {
"filter" : {
"term": {
"extend": ["hello", "world"]
}
}
}
}
}
返回查询:
代码块
GET /oplog/product_oplog/_search
{
"query" : {
"constant_score" : {
"filter" : {
"range": {
"price": {
"gte": 10,
"lte": 20
}
}
}
}
}
}
range 查询可同时提供包含(inclusive)和不包含(exclusive)这两种范围表达式,可供组合的选项如下:
-
gt: > 大于(greater than)
-
lt: < 小于(less than)
-
gte: >= 大于或等于(greater than or equal to)
-
lte: <= 小于或等于(less than or equal to)
2、全文搜索
匹配查询
代码块
GET /oplog/product_oplog/_search
{
"query" : {
"match":{
"diff":"hello"
}
}
}
返回结果:
组合查询:
代码块
GET /oplog/product_oplog/_search
{
"query" : {
"bool":{
"should": [
{"match": {"diff": "hello"}},
{"match": {"extend": "hello"}}
]
}
}
}
短语匹配:
代码块
GET /oplog/product_oplog/_search
{
"query": {
"match_phrase": {
"diff": "hello"
}
}
}
四、聚合
聚合是一种基于搜索的数据汇总,通过组合可以完成复杂的操作。聚合可以对文档中的数据继续统计汇总、分组等,对一个聚合进行操作可以看作在一组文档中分析数据。
对某个字段进行聚合的时候需要将该字段的fileddata设置为true,否则无法聚合
代码块
PUT oplog/_mapping/product_oplog
{
"properties": {
"diff": {
"type": "text",
"fielddata": "true"
}
}
}
1、度量聚合
在一组文档中对某一个数字型字段进行计算得出指标值。数字型度量聚合是一种特殊类型的度量聚合,输出数字类型的值。聚合输出一个数字指标(例如平均值聚合)称为单值数字型度量聚合,产生多个指标值(例如统计聚合)称为多值数字型度量聚合。
-
平均值聚合
代码块
GET /oplog/product_oplog/_search
{
"size" : 0,
"aggs": {
"diff": {
"terms": {
"field": "diff"
},
"aggs": {
"avg_price": {
"avg": {
"field": "price"
}
}
}
}
}
}
聚合类型是avg
结果:
-
基数聚合
假设你在索引oplog而且想要统计符合条件的作者
代码块
GET /oplog/product_oplog/_search
{
"size" : 0,
"aggs": {
"diff": {
"terms": {
"field": "diff"
},
"aggs": {
"diff_count": {
"cardinality": {
"field": "diff"
}
}
}
}
}
}
返回结果:
-
最大值聚合
代码块
GET /oplog/product_oplog/_search
{
"size" : 0,
"aggs": {
"diff": {
"terms": {
"field": "diff"
},
"aggs": {
"max_price": {
"max": {
"field": "price"
}
}
}
}
}
}
结果:
-
最小值聚合
-
和聚合
-
值计数聚合
-
统计聚合
-
百分比聚合
2、分组聚合
分组聚合不像度量聚合哪有通过字段进行计算,而是根据文档创建分组。每个聚合都关联一个标准(取决于聚合的类型),决定了一个文档在当前条件下是否会“划入”分组中。换句话说,分组实际上定义了一个文档集。除了这些分组外,分组聚合也会计算和返回划入每个分组中文档的数量。
-
范围聚合
在聚合过程中,从每个文件中提取的值将根据每个存储区范围进行检查,并对相关/匹配文档进行“bucket”,值得注意的是,注意,此聚合包含了from值,不包括每个范围的to的值。
代码块
GET /oplog/product_oplog/_search
{
"size" : 0,
"aggs": {
"price_range":{
"range": {
"field": "price",
"ranges": [
{
"from": 0,
"to": 100
}
]
}
}
}
}
返回结果:
-
过滤聚合
过滤聚合是一个单分组聚合,包含当前文档集中所有匹配指定的过滤条件的文档。通常是用于从当前聚合中得到一个具体的文档集
代码块
GET /oplog/product_oplog/_search
{
"size" : 0,
"aggs" : {
"diff_products" : {
"filter" : {"term":{"diff": "macbook"}}
}
}
}
返回结果:
-
多重过滤聚合
-
索引值聚合
索引词聚合是一个基于聚合产生一个多组的值,每个分组都是由一个独特的值动态创建。
代码块
GET /oplog/product_oplog/_search
{
"size" : 0,
"aggs" : {
"terms" : {
"terms" : {
"field" : "diff"
}
}
}
}
结果:
3、管道聚合
功能都是实验性质,在将来的版本可能会被修改或删除。