Elasticsearch快速上手篇

学习背景

由于最近工作需要,需要大量使用elasticsearch代替mysql数据库进行数据存储和查询操作,但是目前关于相关的学习文档较少,官方文档看着也较为费劲。所以记录一下我的学习记录。

介绍

Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式的全文搜索引擎,基于restful web接口。Elasticsearch是用Java语言开发的,基于Apache协议的开源项目,是目前最受欢迎的企业搜索引擎。Elasticsearch广泛运用于云计算中,能够达到实时搜索,具有稳定,可靠,快速的特点。
关于Elasticsearch和可视化项目kibana的安装这里就不多做介绍,需要的可以自行百度检索安装。

与Mysql数据库的对应关系

ElasticsearchMysql
索引(index)数据库(databases)
类型(type)表(table)
文档(document)行(row)

在Elasticsearch 7.X以后,官方将过度性移除类型(type),在8.X以后将完成移除type。此时Elasticsearch 数据结构将为两层结构:索引和文档。

Elasticsearch基本操作

  • 在学习Elasticsearch基本操作命令之前需要了解restful风格接口在其应用中的规范
请求类型作用差异
GET查询操作
PUT添加和修改操作在进行添加操作时必须指定文档id,否则报错
POST基本的查询操作在添加时可以不指定文档id,系统会随机为其生成一个文档id
DELETE删除操作
1. 增删改操作
1.1 增加操作(POST、PUT)

将name=小明,age=12数据插入到索引为test,类型为dd中保存

  • 使用POST添加并且不带文档id
POST test/dd/
{
  "name" : "小明",
  "age" : 12
}

返回的结果:

{
  "_index" : "test",
  "_type" : "dd",
  "_id" : "z3EduXoBtsMqPf0VWJNp",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}

其结果中的result字段代表了该操作的状态和类型,"created"表示新添加的并且成功了。并且该数据所在的索引、类型和文档id都进行了显示。当POST没有指定文档id时,系统会自动创建一个随机id。

  • 使用POST添加并且带文档id
POST test/dd/1
{
  "name" : "小强",
  "age" : 13
}

其结果为:

{
  "_index" : "test",
  "_type" : "dd",
  "_id" : "1",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}

可以看出当带上文档id时,其就使用用户指定的id。

  • 使用PUT添加
PUT test/dd/2
{
  "name" : "小文",
  "age" : 14
}

其结果和前面一样,这里就不再赘述。
当使用PUT进行添加操作时,如果不指定文档id时,将会报错。如下所示:

{
  "error" : "Incorrect HTTP method for uri [/test/dd/?pretty=true] and method [PUT], allowed: [POST]",
  "status" : 405
}
1.2 修改操作(POST、PUT)

修改操作和新增操作一样,主要区别是,修改的前提必须在需要修改的索引-类型-文档id下已经存在数据。并且其返回结果的表示为:updated

1.3 删除操作(DELETE)

删除数据的语句可分为两类:

1、DELETE 索引   //删除整个所有下的全部数据,相当于mysql的drop database 数据库名
2、DELETE 索引/类型/文档id  //删除某个文档id下的数据,相当于mysql的delete操作(删除一行)

Elasticsearch不支持删除类型操作,需要删除类型的话,就把该类型下的所有数据删除即可。

2. 查询操作
  • 为了更好的进行后续操作,本文将导入官方提供的测试数据。执行下面语句完成导入
/**
*_bulk为elasticsearch的批量插入操作关键字,在索引为info,类型为account下插入数据
*/
POST /info/account/_bulk                     
  复制测试文件里的所有内容    
  • 测试数据文件地址:链接:https://pan.baidu.com/s/1SW1hC9io1iEt1aSwYcvAPA 提取码:1234
2.1 简单查询
  • 全索引查询
GET /bank/_search

其结果如下所示:由于数据太多,这里只展示第一条数据,后续数据省略。

{
  "took" : 339,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1000,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "info",
        "_type" : "account",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "account_number" : 1,
          "balance" : 39225,
          "firstname" : "Amber",
          "lastname" : "Duke",
          "age" : 32,
          "gender" : "M",
          "address" : "880 Holmes Lane",
          "employer" : "Pyrami",
          "email" : "amberduke@pyrami.com",
          "city" : "Brogan",
          "state" : "IL"
        }
      },
      ......

我们从hits内的hits可以查看到数据对应的键值对。下面将通过这些键值对完成复杂操作的查询。

  • 指定文档id查询
  • 假如我们想查询第一条数据,则可以通过制定文档id完成制定数据查询
GET /info/account/1
2.2 DSL语句查询
  • elasticsearch查询模板
GET /索引名/_search   //带前缀 "_" 的都是elasticsearch自带的关键字
{
  "query": {
     "想要查询的类型":{
     }
  }
}
  • 全数据查询(match_all)
GET /info/_search
{
  "query": {
    "match_all": {}
  }
}
  • 指定字段查询
1、通过match关键字查询
GET /info/_search
{
  "query": {
    "match": {
      "FIELD": "TEXT"
    }
  }
}
2、通过term关键字查询
GET /info/_search
{
  "query": {
    "term": {
      "FIELD": "TEXT"
    }
  }
}
3、通过match_phrase关键字查询
GET /info/_search
{
  "query": {
    "match_phrase": {
      "FIELD": "TEXT"
    }
  }
}

上面三种关键字都可以对指定字段进行查询,其主要区别如下表所示:

关键字特点案例(查询"雷神")
match模糊查询(text类型),会对待字段进行分词操作,只要包含该字段和其分词后的字都可以查询到。,只要包含"雷",“神”, "雷神"这些关键字的字段都会被查询到
term精准查询,将待查询的字段视为keyword类型,不会对其进行分词操作只能查询到包含"雷神"的字段
match_phrase精准查询,会进行分词操作,与match主要不同的是,其会查询包含所有分词后的语句并且其顺序要和原有顺序一致,相当于一种段落精准查询。进行分词为"雷",“神”, “雷神”,可以查询到顺序和分词顺序一致的结果
  • bool查询
    bool类型共包含四种查询类型:must、must_not、should、filter。
GET /info/_search
{
  "query": {
    "bool": {
      "must": [   //必须包含
        {
          "match": {
            "FIELD": "TEXT"
          }
        }
      ],
      "must_not": [  //一定不包含
        {
          "match": {
            "FIELD": "TEXT"
          }
        }
      ],
      "should": [   //可以包含,相当于or
        {
          "match": {
            "FIELD": "TEXT"
          }
        }
      ],
      "filter": [   //指定字段进行查询
        {
          "term": {
            "FIELD": "VALUE"
          }
        }
      ]
    }
  }
}

从上面可以看出,关键字filter的和query的功能相似,但是其由一定的差异,如下表

关键字特点
query进行基本的查询操作,同时对查询的结果贡献相关性得分,从而使结果进行排序
filter只有查询操作,其查询的结果不会贡献相关性得分
  • 范围查询
    如果我们想想Mysql一样使用">“或者”<"符合来查询范围区间时,在elasticsearch中可以使用关键字"range"来完成,具体格式如下,该关键字和match等关键字一样,可以使用在同样位置。
"range": {
      "age": {
        "gt(e)": value1,   //大于(等于)value1
        "lt(e)": value2    //小于(等于)value2
      }
    }
  • 聚合查询

    • 聚合查询其含义与Mysql的聚合函数相似,可以为我们提高对数据的分析操作。其关键字为"aggs"
      其格式如下所示:
"aggs": {                     //聚合查询关键之,用来声明一个聚合查询段落
    "name": {                 //自己定义的聚合查询的名称
      "AGG_TYPE": {           //聚合的类型  
        "field": field,       //指定需要聚合操作的字段名称  
      }
    }
  }

elasticsearch提供了较多的聚合类型,常见的类型分为如下关键字:terms、sum、max、min、avg等。其中后四种用法相同,如上模板所示,其功能主要对指定的字段进行相应的求和、求最大值、最小值、均值等。但是对于terms关键字用法有些区别,具体如下:

  "aggs": {
    "aggGender": {
      "terms": {
      /**
      *  需要聚合操作的字段名,**需要注意的是:对于text类型的字段,
      *  需要使用filed.keyword类型进行聚合,类似于查询关键字term**
      */
        "field": "field", 
        "size": n   //聚合后展示的数量大小,默认10
      }
    }
 }

例如下面的一段查询操作:

GET info/_search
{
  "query": {
    "match": {
      "address": "mill"
    }
  },
  "aggs": {
    "aggGender": {
      "terms": {
        "field": "gender.keyword",
        "size": 10
      }
    }
  }
}

上面的操作含义为:首先对address字段进行模糊查询,后面的聚合操作时基于前面的查询结果进行聚合操作。按照性别进行聚合,也就是将"男"和"女"字段的数据进行分组。结果如下所示

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,   //共查询到4条数据
      "relation" : "eq"
    },
    "max_score" : 5.4032025,
    "hits" : [
	    {
	       这里为了方便展示全部数据,将查询到的结果数据进行省略
	    }
    ]
  },
  //聚合函数结果
  "aggregations" : {
    "aggGender" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "M",
          "doc_count" : 3    //表示查询出来的4条数据中有3条是男性
        },
        {
          "key" : "F",
          "doc_count" : 1    //表示查询出来的4条数据中有1条是女性
        }
      ]
    }
  }
}

  • 嵌套聚合操作
    当我们想对上一步聚合后的结果进行更加细粒度化,就可以在原有基础上再封装一层聚合操作。比如我们需要得到从上述查询出来的数据中,男女不同性别的平均薪水。
GET info/_search
{
  "query": {
    "match": {
      "address": "mill"
    }
  },
  "aggs": {
    "aggGender": {
      "terms": {
        "field": "gender.keyword",
        "size": 10
      },
      //在上一步聚合后,再进行一层嵌套聚合操作
      "aggs": {
        "aggBalanceAvg": {
          "avg": {      //基于前面的聚合数据获取薪资均值
            "field": "balance"   //薪资字段balance
          }
        }
      }
    }
  }
}

输出结果如下所示:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 5.4032025,
    "hits" : [
   	    {
       		这里为了方便展示全部数据,将查询到的结果数据进行省略
    	}
    ]
  },
  "aggregations" : {
    "aggGender" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "M",
          "doc_count" : 3,
          "aggBalanceAvg" : {  //二次子聚合名称
            "value" : 25087.0   //男性中的平均薪水
          }
        },
        {
          "key" : "F",
          "doc_count" : 1,
          "aggBalanceAvg" : {
            "value" : 25571.0  //女性中的平均薪水
          }
        }
      ]
    }
  }
}

好了,学到这里,你对es的基本入门操作已经大概了解了,下一遍将会继续讲解elasticsearch的高级客户端的基本使用,也即整合到springboot的使用。

这是本人的第一篇博客,有不足之处还望各位老哥多多指点,后续将会持续输出更多互联网公司必备的技术和学习心得。
关注我的公众号,让我们一起交流学习

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值