ElasticSearch的学习总结(包含API)


ElasticSearch_总结

1.lucene

lucene,就是一个jar包,里面包含了封装好的各种建立倒排索引,以及进行搜索的代码,包括各种算法。我们就用java开发的时候,引入lucene jar,然后基于lucene的api进行去进行开发就可以了。

2.倒排索引

可以看到 Lucene 为倒排索引(Term Dictionary)部分又增加一层Term Index结构,用于快速定位,而这Term Index是缓存在内存中的,但MySQL的B+tree不在内存中,所以整体来看ES速度更快,但同时也更消耗资源(内存、磁盘)。

3.B+tree

是B-Tree的改进版本,同时也是数据库索引索引所采用的存储结构。数据都在叶子节点上,并且增加了顺序访问指针,每个叶子节点都指向相邻的叶子节点的地址。相比B-Tree来说,进行范围查找时只需要查找两个节点,进行遍历即可。而B-Tree需要获取所有节点,相比之下B+Tree效率更高。(排序查找算法系统的学习,可以在Java知音公众号回复“排序算法聚合”)

MySQL使用的B+tree 是B-Tree的改进版本,同时也是数据库索引索引所采用的存储结构。数据都在叶子节点上,并且增加了顺序访问指针,每个叶子节点都指向相邻的叶子节点的地址。相比B-Tree来说,进行范围查找时只需要查找两个节点,进行遍历即可。而B-Tree需要获取所有节点,相比之下B+Tree效率更高。(排序查找算法系统的学习,可以在Java知音公众号回复“排序算法聚合”)

3.Elasticsearch核心概念

3.1近实时

近实时,两个意思,从写入数据到数据可以被搜索到有一个小延迟(大概1秒);基于es执行搜索和分析可以达到秒级。

3.2Cluster(集群)

集群包含多个节点,每个节点属于哪个集群是通过一个配置(集群名称,默认是elasticsearch)来决定的,对于中小型应用来说,刚开始一个集群就一个节点很正常

#cluster.name
#-----------------------------------------------
#1 如果要配置集群需要两个节点上的elasticsearch配置的cluster.name相同,都启动可以自动组成集群,这里如果不改cluster.name则默认是cluster.name=my-application
#2 nodename随意取但是集群内的各节点不能相同
#3 修改后的每行前面不能有空格,修改后的“:”后面必须有一个空格

3.3Node(节点)

集群中的一个节点,节点也有一个名称(默认是随机分配的),节点名称很重要(在执行运维管理操作的时候),默认节点会去加入一个名称为“elasticsearch”的集群,如果直接启动一堆节点,那么它们会自动组成一个elasticsearch集群,当然一个节点也可以组成一个elasticsearch集群。

3.4Index(索引-数据库)

索引包含一堆有相似结构的文档数据,比如可以有一个客户索引,商品分类索引,订单索引,索引有一个名称。一个index包含很多document,一个index就代表了一类类似的或者相同的document。比如说建立一个product index,商品索引,里面可能就存放了所有的商品数据,所有的商品document。

3.5Type(类型-表)

6.0版本之前每个索引里都可以有多个type;

6.0版本之后每个索引里面只能有一个Type,一般使用_doc代替了。

商品index,里面存放了所有的商品数据,商品document

商品type:product_id,product_name,product_desc,category_id,category_name,service_period

每一个type里面,都会包含一堆document

{
  "product_id": "1",
  "product_name": "长虹电视机",
  "product_desc": "4k高清",
  "category_id": "3",
  "category_name": "电器",
  "service_period": "1年"
}

3.6Document(文档-行)

文档是ES中的最小数据单元,一个document可以是一条客户数据,一条商品分类数据,一条订单数据,通常用JSON数据结构表示,每个index下的type中,都可以去存储多个document。

3.7Field(字段-列)

一个document里面有多个field,每个field就是一个数据字段。

#product document
{
  "product_id": "1",
  "product_name": "高露洁牙膏",
  "product_desc": "高效美白",
  "category_id": "2",
  "category_name": "日化用品"
}

3.8Mapping(映射-约束)

数据如何存放到索引对象上,需要有一个映射配置,包括:数据类型、是否存储、是否分词等。

Mapping用来定义Document中每个字段的类型,即所使用的分词器、是否索引等属性,非常关键等。

3.9ElasticSearch与数据库的类比

关系型数据库(比如Mysql) 非关系型数据库(Elasticsearch)
数据库Database 索引Index
表Table 类型Type(6.0版本之后在一个索引下面只能有一个,7.0版本之后取消了Type)
数据行Row 文档Document(JSON格式)
数据列Column 字段Field
约束 Schema 映射Mapping

3.10ElasticSearch存入数据和搜索数据机制

ElasticSearch索引结构

1)索引对象(blog=index):存储数据的表结构,任何搜索数据,存放在索引对象上 。

2)映射(mapping):数据如何存放到索引对象上,需要有一个映射配置, 包括:数据类型、是否存储、是否分词等。

3)文档(document):一条数据记录,存在索引对象上。

4)文档类型:一个索引对象,存放多种类型数据,数据用文档类型进行标识。

4.总结

总而言之 搜索是把所有数据进行json格式化,格式化的方法使用Mapping映射约束成json文件,然后赋予Docid,然后通过倒排索引的方法将字段提取出来,提供 索引(Docid结构)

5.代码

#查看元数据信息
GET _cat/nodes
GET _cat/health
GET _cat/indices
GET _cat/master

#手动创建Mapping
PUT student
{
  "mappings": {
    "_doc":{
      "properties":{
        "stu_id":{
          "type":"keyword"
        },
        "name":{
          "type":"text"
        },
        "gender":{
          "type":"boolean"
        },
        "birth":{
          "type":"date"
        }
      }
    }
  }
}

#查看Mapping信息
GET student/_mapping

#使用PUT方式向student索引中插入数据:幂等操作
PUT student/_doc/1001
{
  "stu_id":"1111",
  "name":"张三",
  "gender":false,
  "birth":"2020-12-05"
}

#插入错误类型的数据
PUT student/_doc/1002
{
  "stu_id":"2222",
  "name":"李四",
  "gender":"aaaa",
  "birth":"2020-12-05"
}

#使用POST方式向student索引中插入数据
POST student/_doc
{
  "stu_id":"2222",
  "name":"李四",
  "gender":true,
  "birth":"2020-12-05"
}

#查询索引数据
GET student/_search

#自动创建Mapping(直接向一个不存在的Index中插入数据即可)
PUT student1/_doc/1001
{
  "stu_id":1111,
  "name":"张三",
  "gender":false,
  "birth":"2020-12-05"
}

#查询自动创建Mapping的映射信息
GET student1/_mapping

#查看keyWord类型分词结果(报错,不分词)
GET _analyze
{
  "keyword":"我是程序员"
}

#查看Text类型分词结果(将汉字独立拆开)
GET _analyze
{
  "text":"我是程序员"
}

#查看使用IK分词器之后的分词效果
GET _analyze
{
  "analyzer": "ik_smart",
  "text":"我是程序员"
}

GET _analyze
{
  "analyzer": "ik_max_word",
  "text":"我是程序员"
}

#创建Index
PUT stu1
{
  "mappings": {
    "_doc":{
      "properties":{
        "stu_id":{
          "type":"keyword"
        },
        "name":{
          "type":"keyword"
        },
        "class_id":{
          "type":"integer"
        },
        "gender":{
          "type":"text"
        },
        "age":{
          "type":"integer"
        },
        "favo1":{
          "type":"keyword"
        },
        "favo2":{
          "type":"text",
          "analyzer": "ik_max_word"
        }
      }
    }
  }
}

#插入测试数据
PUT stu1/_doc/1001
{
  "stu_id":"1111",
  "name":"国亮",
  "class_id":"0720",
  "gender":"male",
  "age":18,
  "favo1":"唱歌跳舞,乒乓球",
  "favo2":"唱歌跳舞,乒乓球"
}

PUT stu1/_doc/1002
{
  "stu_id":"2222",
  "name":"王斌",
  "class_id":"0720",
  "gender":"male",
  "age":3,
  "favo1":"睡觉,做梦,梦游",
  "favo2":"睡觉,做梦,梦游"
}

PUT stu1/_doc/1003
{
  "stu_id":"3333",
  "name":"班长",
  "class_id":"0720",
  "gender":"female",
  "age":17,
  "favo1":"抽烟,喝酒,烫头,羽毛球",
  "favo2":"抽烟,喝酒,烫头,羽毛球"
}

PUT stu1/_doc/1004
{
  "stu_id":"4444",
  "name":"文康",
  "class_id":"0720",
  "gender":"male",
  "age":60,
  "favo1":"太极,广场舞,闪电舞",
  "favo2":"太极,广场舞,闪电舞"
}

PUT stu1/_doc/1005
{
  "stu_id":"5555",
  "name":"加明",
  "class_id":"0720",
  "gender":"male",
  "age":22,
  "favo1":"蹦迪,大保健,洗脚",
  "favo2":"蹦迪,大保健,洗脚"
}

PUT stu1/_doc/1006
{
  "stu_id":"6666",
  "name":"张小芳",
  "class_id":"0720",
  "gender":"female",
  "age":24,
  "favo1":"来,手机交一下,胸卡口罩戴起来",
  "favo2":"来,手机交一下,胸卡口罩戴起来"
}

PUT stu1/_doc/1007
{
  "stu_id":"7777",
  "name":"马丁",
  "class_id":"0523",
  "gender":"male",
  "age":70,
  "favo1":"_省略,scala,编程,橄榄球",
  "favo2":"_省略,scala,编程,橄榄球"
}

PUT stu1/_doc/1008
{
  "stu_id":"8888",
  "name":"安小妮",
  "class_id":"0523",
  "gender":"female",
  "age":30,
  "favo1":"来,手机交一下,胸卡口罩戴起来",
  "favo2":"来,手机交一下,胸卡口罩戴起来"
}

#查询数据
GET stu1/_search

#全值匹配查询filter(where):指的是将查询条件当做一个整体
GET stu1/_search
{
  "query": {
    "bool": {
      "filter": {
        "term": {
          "favo1": "来,手机交一下,胸卡口罩戴起来"
        }
      }
    }
  }
}

GET stu1/_search
{
  "query": {
    "bool": {
      "filter": {
        "term": {
          "favo2": "来,手机交一下,胸卡口罩戴起来"
        }
      }
    }
  }
}

#分词匹配match:将查询条件做分词,但是使用的分词规则与原字段相同
GET stu1/_search
{
  "query": {
    "match": {
      "favo1": "来,手机交一下,胸卡口罩戴起来"
    }
  }
}

GET stu1/_search
{
  "query": {
    "match": {
      "favo2": "来,手机交一下,胸卡口罩戴起来"
    }
  }
}

GET stu1/_search
{
  "query": {
    "match": {
      "favo1": "球"
    }
  }
}

GET stu1/_search
{
  "query": {
    "match": {
      "favo2": "球"
    }
  }
}

#结合全值匹配以及分词匹配查询
#需求,查询出0720班级爱好包含"球"
GET stu1/_search
{
  "query": {
    "bool": {
      "filter": {
        "term": {
          "class_id": "0720"
        }
      },
      "must": [
        {
          "match": {
            "favo2": "球"
          }
        }
      ]
    }
  }
}

#模糊查询
GET stu1/_search
{
  "query": {
    "fuzzy": {
      "gender": "female"
    }
  }
}

#聚合查询:单个聚合条件
GET stu1/_search
{
  "aggs": {
    "countByClass": {
      "terms": {
        "field": "class_id",
        "size": 10
      }
    }
  }
}

GET stu1/_search
{
  "aggs": {
    "maxAge": {
      "max": {
        "field": "age"
      }
    }
  }
}


#聚合查询:多个聚合条件:没有关联
GET stu1/_search
{
  "aggs": {
    "countByClass": {
      "terms": {
        "field": "class_id",
        "size": 10
      }
    },
    "maxAge": {
      "max": {
        "field": "age"
      }
    }
  }
}

#聚合查询:多个聚合条件:嵌套关联
GET stu1/_search
{
  "aggs": {
    "countByClass": {
      "terms": {
        "field": "class_id",
        "size": 10
      },
      "aggs": {
        "maxAge": {
          "max": {
            "field": "age"
          }
        }
      }
    }
  }
}

#分页查询  from=(页码-1)*size
GET stu1/_search
{
  "from": 2,
  "size": 2
}

#综合需求:查询0720班级爱好包含"球"的人,并计算其中最大年纪是多少,同时使用分页查询
GET stu1/_search
{
  "query": {
    "bool": {
      "filter": {
        "term": {
          "class_id": "0720"
        }
      },
      "must": [
        {
          "match": {
            "favo2": "球"
          }
        }
      ]
    }
  },
  "aggs": {
    "maxAge": {
      "max": {
        "field": "age"
      }
    }
  },
  "from": 1,
  "size": 1
}

文章作者: Jinxin Li
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Jinxin Li !
  目录