一、ES简介
Elasticsearch是基于Json的分布式搜索和分析引擎,是利用倒排索引实现的全文索引。
倒排索引通俗的理解就是:
搜索数据库的时候 要select * from B 这时候我们知道表名去找数据
但是网络中 我们想搜索的东西可能分别存放在无数个数据库中,这时候我们要反着去找
select 表 from * 给一个想要的数据 来搜索他在哪个表中
就像淘宝搜索某个商品,会出来这个商品在哪些商店里,而不是搜索店铺里有什么商品。
二、ES核心概念与关系数据库对比
Relational DB | Elasticsearch |
---|---|
数据库(database) | 索引(index) |
表(tables) | 类型(types) |
行(rows) | 文档( documents) |
列(columns) | 字段(fields) |
Schema | Mapping |
三、初步检索
1、_cat
GET /_cat/nodes:查看所有节点
GET /_cat/health:查看es健康状况
GET /_cat/master:查看主节点
GET /_cat/indices:查看所有索引
2、索引一个文档(保存)
保存一个数据,保存在哪个索引的哪个类型下,指定用哪个唯一标识
PUT customer/external/1
{
"name":"lohn Doe"
}
在customer索引下的external类型下保存1号数据
PUT和 POST都可以,
POST 新增。如果不指定id,会自动生成id。指定id就会修改这个数据,并新增版本号
PUT可以新增可以修改。PUT必须指定id,由于PUT需要指定id,我们一般都用来做修改操作,不指定id会报错。
3、查询文档
GET clstomer/external/1
结果
{
"_index": "customer", //在哪个索引
"_type": "external", //在哪个类型
"_id":"1", //记录id
"_version":2, //版本号
"_seq_no":1, //并发控制字段,每次更新就会+1,用来做乐观锁
"_primary_term":1, //同上,主分片重新分配,如重启,就会变化
"found": true,
"_source":{
"name": "John Doe"
}
}
更新携带?if_seg_no=0&if_primary_term=1
4、更新文档
POST customer/external/1/_update
{
"doc":{
"name": "lohn Doew"
}
}
或者
POST customer/external/1
{
"name":"John Doe2"
}
或者
PUT customer/external/1
{
"name":"John Doe"
}
不同:POST操作会对比源文档数据,如果相同不会有什么操作,文档version不增加
PUT操作总会将数据重新保存并增加version版本,带_update对比元数据如果一样就不进行任何操作。
看场景,
对于大并发更新,不带updates
对于大并发查询偶尔更新,带update)对比更新,重新计算分配规则。
更新同时增加属性
POST customer/external/1/_update
{
"doc":{ "name": "Jane Doe","age":20}
}
5、删除文档和索引
DELETE customer/external/1 //删除文档
DELETE customer //删除索引
ES没有删除类型的操作
6、bulk批量API
POST customer/external/_bulk
{"index":{"_id":"1"}}
{"name":""John Doe" }
{"index":{"_id":"2"}}
{"name":"Jane Doe" }
语法格式:
{action:{metadata}} \n
{ request body} n
{action:{metadata}} \n
{request body } \n
复杂实例:
POST /_bulk
{ "delete":{"_index": "website","_type":"blog","_id":"123"}}
{ "create":{"_index": "website","_type":"blog","_id":"123"}}
{ "title":"My first blog post"}
{"index":{"_index": "website","_type" :"blog"}}
{"title":"My second blog post"}
{"update":{"_index": "website", "_type": "blog","_id":"123","_retry_on_conflict":3}}
{"doc" : {"title" : "Myupdated blog post"}}
bulkAPI以此按顺序执行所有的action(动作)。如果一个单个的动作因任何原因而失败,它将继续处理它后面剩余的动作。当bukAPr返回时,它将提供每个动作的状态(与发送的顺序相同),所以您可以检查是否一个指定的动作是不是失败了。
四、进阶检索
1)、基本语法格式
Elasticsearch提供了一个可以执行查询的Json风格的DSL (domain-speific language领域特定语言)。这个被称为Query DSL。该查询语言非常全面,并且刚开始的时候感觉有点复杂, 真正学好它的方法是从一些基础的示例开始的。
一个查询语句的典型结构
GET bank/_search
{
"query":{
"match_all":{}
}
"from":0,
"size":5,
"sort":[
{
"account_number":{
"order":"desc"
}
],
"_source" : {"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32}
}
}
- query 定义如何查询
- match_all 查询类型【代表查询所有的所有】,es中可以在query中组合非常多的查询类型完成复杂查询
- 除了query 参数之外,我们也可以传递其它的参数以改变查询结果。如sort,size
- frome size限定,完成分页功能
- sort 排序,多字段排序,会在前序字段相等时后续字段内部排序,否则以前序为准
- source 返回的指定的字段
2)、match【匹配查询,分词】
GET bank/_search
{
"query":{
"match":{ "account_number":"20"}
}
match返回account_number=20(account_number是数值类型)的文档
GET /bank/_search
{
"query": {
"match": { "address": "mill lane" }
}
}
match 返回address中包含mill、lane(分词) 的文档
数值类型匹配相当于相等,非数值类型则是包含
3)、match_phrase【短语匹配,不分词】
将需要匹配的值当成一个整体单词(不分词)进行检索
GET /bank/_search
{
"query": {
"match_phrase": { "address": "mill lane" }
}
}
查出address中包含mill road 的所有记录,并给出相关性得分
3)、multi_match【多字段匹配,会进行分词】
GET /bank/_search
{
"query": {
"multi_match":{
"query":"mill movico",
"filed":["address","city"]
}
}
}
相当于sql中的
where address like '%mill%'
or address like '%movico%'
or city like '%mill%'
or city like '%movico%'
4)、bool 布尔查询(must、must not、should、filter)
GET /bank/_search
{
"query": {
"bool" : {
"must" :[
{"match" : { "gender" : "M" }},
{"match" :{"address" : "mill"}}
],
"must_not" : {
"match" : {"age":"18"}
},
"should" : [
{ "match" : { "lastname" : "wallence" } }
]
}
}
}
相当于sql
where gender = ‘M’
and address like '%mill%'
and age != 18
or lastname like '%wallence%'
must:子句(查询)必须出现在匹配的文档中,并将有助于得分。
filter:子句(查询)必须出现在匹配的文档中。然而,不像must查询的分数将被忽略。过滤器子句在过滤上下文,这意味着忽略了评分,并考虑了用于缓存的子句。
should:子句(查询)应该出现在匹配的文档中。
must_not:子句(查询)不能出现在匹配的文档中。子句在过滤上下文这意味着忽略了评分,并考虑了用于缓存的子句。因为得分被忽略,0因为所有的文件都会被退回。
4)、term 和match一样,匹配某个属性的值,term是完全匹配,相当sql中的等于
ElasticSearch7-去掉type概念
关系型数据库中两个数据表示是独立的,即使他们里面有相同名称的列也不影响使用, 但ES中不是这样的。elasticsearch是基于Lucene开发的搜索引擎,而ES中不同type 名称相同的filed最终在Lucene中的处理方式是一样的。
两个不同type下的两个user_name,在ES同一个索引下其实被认为是同一个filed, 你必须在两个不同的type中定义相同的filed映射。否则,不同type中的相同字段 名称就会在处理中出现冲突的情况,导致Lucene处理效率下降。去掉type就是为了提高ES处理数据的效率。
Elasticsearch 7.x
URL中的type参数为可选。比如,索引一个文档不再要求提供文档类型。. Elasticsearch 8.x不再支持URL中的type参数。
解决:将索引从多类型迁移到单类型,每种类型文档一个独立索引
五、Mapping映射
Mapping是用来定义一个文档(document),以及它所包含的属性(field)是如何存储和索引的。比如,使用mapping来定义哪些字符串属性应该被看做全文本属性(full text fields)。哪些属性包含数字,日期或者地理位置。文档中的所有属性是否都能被索引(_all配置)。
// 查看映射信息
GET bank/_mapping
//创建具有显示映射的索引
PUT /my-index
{
"mappings": {
"properties": {
"age": { "type": "integer" },
"email": { "type": "keyword" },
"name": { "type": "text" }
}
}
}
// 新增字段到现有索引中
PUT my-index/_mapping
{
"properties": {
"employee-id": {
"type": "keyword",
"index": false //是否能够被索引到,默认为true
}
}
}