Elasticsearch笔记


本文kibana操作es部分摘抄自:https://zhuanlan.zhihu.com/p/134104899

我的elasticsearch版本是7.9.1

这里首先分享一个超级超级给力的 postman 文件,关于es7.9.1版本的操作基本上面都有,地址:
https://anyongliang.oss-cn-beijing.aliyuncs.com/blog/web/file/es-7.9.1.json

打开地址,
复制里面的内容,
自己新建一个.json文件,
复制进去,
打开postman导入(import)那个.json文件,
然后就可以看到里面牛皮Plus的内容了!!!

放个截图你们感受一下
在这里插入图片描述

好的,开始正文…

一.什么是Elasticsearch

关于这个问题网络上有太多的答案了,我就不去一一的复制粘贴过来了,写一写自己的理解吧,如有错误,麻烦评论留(打)言(脸)…

  • 它是RESTful 风格的搜索和数据分析引擎,底层引擎使用开源库Apache Lucene。
  • Apache Lucene这玩意儿用起来太复杂了,所有就有了Elasticsearch,所以,偷懒使人进步…
  • Elasticsearch还具备其他功能:
     1.一个分布式的实时文档存储,每个字段可以被索引与搜索;
     2.一个分布式实时分析搜索引擎;
     3.能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据。
     4.算法原理:倒排索引,b+树。
     总结下来就是,这玩意简单,功能强大,不要问,问就好用

二.Elasticsearch使用相关安装

 额…因为这里使记录elasticsearch的使用,所以安装这一块略去,大概说一下要安装的东西:
1.安装elasticsearch
2.要用elasticsearch,就必须要java,所以要安装java
3.安装 ElasticSearch head插件(这个不是必须装,装了的话用起来方便点),图形化管理es, 可以参考 [https://www.cnblogs.com/qiyu/p/12654883.html](https://www.cnblogs.com/qiyu/p/12654883.html
4.都安装那么多了,再装个kibana吧…
这里确实是我懒了,安装方面网上有很多教程,各种系统都能找到,所以要先安装一下


三.Elasticsearch相关概念

 1.es是面向文档的,所以可以存储整个对象或者文档,它还可以索引每个文档里面的内容来进行搜索,可以对整个文档进行索引,搜索,排序和过滤。
来看一下es和mysql之间的对应大概对应关系
在这里插入图片描述
其实把类型tpye比做mysql中的tables表,是不对的,在elasticsearch7.0之后一个索引中只允许创建一个类型,如果想创建多个类型映射:

  • 方法1:每个文档类型都有索引。
    您可以在推特 微信索引 和 用户索引 中存储 微信,而不是在单个微信索引中存储 微信 和 用户。索引是完全独立的,因此在索引之间不会有字段类型冲突。
    这种方法的好处:

    • 搜索更为精准,同一个索引中每一个文档都代表单个实体;
    • 可以灵活分配索引空间,可以为用户索引分配较少的分片,为微信索引分配较多的分片;
  • 方法2:在索引名称上动手脚
    这个是我自己的办法,属于无奈之下的骚操作。
    假设需要在es增加如下数据:
    school数据库,里面有user表信息和student表信息,但是不可以创建两个type,所以就创建两个索引
    1.school_user索引:存储school库里面的user表信息;
    2.school_student索引:存储school库里面的student表信息;

ps:索引不能使用大写字母,都得是小写字母;

我描述的可能不太准确,大家看这个大佬的文章, https://elasticsearch.cn/article/337

 下面对概念进行一些解释

  • 索引-index,就是上方图中的indices
      对应关系型数据库的中 库,一个索引由一个名字来标示(必须全部是小写字母), 对这个索引中内容进行操作时候,都要使用这个名字。

  • 类型-type
      一个索引可以定义一种或者多种类型,一个类型就是索引里面的一个逻辑分区,例如你把整个学生管理系统数据存储到一个索引中时,可以为学生定义一个类型,为老师定义一个类型,为课程再定义一个类型。

  • 字段-field
      就是数据表的字段,对不同内容进行分类标示。

  • 映射-mapping
      表结构定义,定义字段的各种属性。

  • 文档-document
      文档是一个可被索引的基础信息单元。你可以拥有一个产品的文档,一个用户的文档等等,文档以json格式来表示。

  • 节点和集群
      一个节点就是一个服务器,多个节点组成一个集群(之后再细说)。


四.开始操作

  1. 增删改查一个索引,打开postman,如图
    • 增加索引
      在这里插入图片描述
      成功之后返回
      在这里插入图片描述
  • 查索引
    在这里插入图片描述
  • 删除索引
    在这里插入图片描述
  1. 用其他方式来操作,打开head(这个要先安装),看到下图,表示创建索引成功
    在这里插入图片描述
  2. 使用kibana创建索引–PUT /movie_index
    在这里插入图片描述
  3. 查询索引信息—GET /movie_index
    在这里插入图片描述
  4. 删除索引–DELETE /movie_index
    删除单独数据(document) DELETE /movie_index/movie/2

ps.多属性查询解释

bool 过滤可以用来合并多个过滤条件查询结果的布尔逻辑,它包含一下操作符:

  • must:多个查询条件的完全匹配,相当于and;
  • must_not:多个查询条件的相反匹配,相当于not;
  • should:至少有一个查询条件匹配,相当于or.

五.kibana操作es增删改查

  1. 新增文档

创建索引并且指定mapping

PUT /xxxxxx
{
  "settings": {
    "number_of_shards": 8,		#分片数
    "number_of_replicas": 1		#备份数
  },
  "mappings": {
  	# type类型
    "_doc":{
      "properties":{
      	# 具体的字段值和字段类型
        "ProductId":{
          "type":"text",
          "analyzer" : "ik_max_word",	# 指定分词器为ik,需要预先安装
          "index" : "true",  # 指定当前字段可以被作为查询的条件
          "store" : false    # 是否需要额外存储
        },
        "EnterpriseName":{
          "type":"text"
        },
        "CompanyId":{
          "type":"text"
        },
        "ProductName":{
          "type":"text"
        },
        "ProductModel":{
          "type":"text"
        }
      }
    }
  }
}

添加数据: movie_index: 索引名,movie: 类型type名, 1: 文档名

PUT /movie_index/movie/1
{ 
	"id":1,
  "name":"operation red sea",
  "doubanScore":8.5,
  "actorList":[  
    {"id":1,"name":"zhang yi"},
    {"id":2,"name":"hai qing"},
    {"id":3,"name":"zhang han yu"}
  ]
}

PUT /movie_index/movie/2
{
  "id":2,
  "name":"operation meigong river",
  "doubanScore":8.0,
  "actorList":[  
    {"id":3,"name":"zhang han yu"}
  ]
}

PUT /movie_index/movie/3
{
  "id":3,
  "name":"incident red sea",
  "doubanScore":5.0,
  "actorList":[  
    {"id":4,"name":"zhang chen"}
  ]
}

  1. 搜索movie表的所有数据: GET/movie_index/movie/_search
    得到回参
{
  "took" : 528,		//整个搜索请求花费多少毫秒
  "timed_out" : false,
  "_shards" : {		//分片信息
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {			//命中信息
    "total" : {
      "value" : 3,		//本次搜索,返回多少条结果
      "relation" : "eq"
    },
    "max_score" : 1.0,		//最大分数,关键字和搜索结果之间的匹配度
    "hits" : [
      {
        "_index" : "movie_index",			//索引
        "_type" : "movie",						//表
        "_id" : "1",									//文档
        "_score" : 1.0,			//匹配度, 命中分数
        "_source" : {			//查询的数据本身
          "id" : 1,
          "name" : "operation red sea",
          "doubanScore" : 8.5,
          "actorList" : [
            {
              "id" : 1,
              "name" : "zhang yi"
            },
            {
              "id" : 2,
              "name" : "hai qing"
            },
            {
              "id" : 3,
              "name" : "zhang han yu"
            }
          ]
        }
      },
      {
        "_index" : "movie_index",
        "_type" : "movie",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "id" : 2,
          "name" : "operation meigong river",
          "doubanScore" : 8.0,
          "actorList" : [
            {
              "id" : 3,
              "name" : "zhang han yu"
            }
          ]
        }
      },
      {
        "_index" : "movie_index",
        "_type" : "movie",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "id" : 3,
          "name" : "incident red sea",
          "doubanScore" : 5.0,
          "actorList" : [
            {
              "id" : 4,
              "name" : "zhang chen"
            }
          ]
        }
      }
    ]
  }
}

  1. 查找指定 id 的 document 数据: GET /movie_index/movie/1

  1. 按照字段分词进行查询
GET /movie_index/movie/_search
{
  "query": {
    "match":{
      "name":"red"
    }
  }
} 

得到回复参数

{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.4700036,			//这里就是匹配度了
    "hits" : [
      {
        "_index" : "movie_index",
        "_type" : "movie",
        "_id" : "1",
        "_score" : 0.4700036,		//这里就是匹配度了
        "_source" : {
          "id" : 1,
          "name" : "operation red sea",
          "doubanScore" : 8.5,
          "actorList" : [
            {
              "id" : 1,
              "name" : "zhang yi"
            },
            {
              "id" : 2,
              "name" : "hai qing"
            },
            {
              "id" : 3,
              "name" : "zhang han yu"
            }
          ]
        }
      },
      {
        "_index" : "movie_index",
        "_type" : "movie",
        "_id" : "3",
        "_score" : 0.4700036,		//这里就是匹配度了
        "_source" : {
          "id" : 3,
          "name" : "incident red sea",
          "doubanScore" : 5.0,
          "actorList" : [
            {
              "id" : 4,
              "name" : "zhang chen"
            }
          ]
        }
      }
    ]
  }
}

  1. 按照分词子属性查询
GET /movie_index/movie/_search
{
  "query": {
    "match": {
      "actorList.name": "zhang"
    }
  }
}

  1. 按照短语查询
    按照短语查询的意思是指, 匹配某个 field 的整个内容, 不再利用分词技术
    把operation red作为一个整体来看待
GET /movie_index/movie/_search
{
  "query": {
    "match_phrase": {
      "name": "operation red"
    }
  }
}

  1. 模糊查询
    校正匹配分词,当一个单词都无法准确匹配,es 通过一种算法对非常接近的单词也给与一定的评分,能够查询出来,但是消耗更多的性能。
GET /movie_index/movie/_search
{
  "query": {
    "match": {
      "字段名": {
          "query":   "模糊匹配的值",
          "fuzziness": "AUTO",
          "operator":  "and"
      }
    }
  }
}

多字段模糊搜索:

{
  "query": {
    "bool": {
      "should": [		//should,或运算关系
        {
          "match": {		//分词
            "EnterpriseName": {		//查询的字段
                 "query":   "大理石",		//查询的值
                 "fuzziness": "AUTO",
                 "operator":  "and"
            }
          }
        },
        {
          "match": {
            "ProductName": {
                 "query":   "大理石",
                 "fuzziness": "AUTO",
                 "operator":  "and"
            }
          }
        },
        {
          "match": {
            "ProductModel": {
                 "query":   "大理石",
                 "fuzziness": "AUTO",
                 "operator":  "and"
            }
          }
        }
      ]
    }
  }
}

这有一个大坑一定要注意,查询的字段mapping必须是text,不能是keyword,keyword的话是不会进行分词的,就是说不能进行模糊匹配!!!

那万一mapping已经定好了改不了怎么办?
重新创建一个,复制数据,然后更改别名…

步骤

  • 查看老的索引的文档接口
    GET 老索引名字/_mapping
  • 创建新索引 : 负责老索引的文档结构
    PUT /新索引名字
  • 迁移老的索引数据到新的索引
POST _reindex
{
 "source": {
   "index": "xxxx"     #老的索引名字
 },
 "dest": {
   "index": "aaasd"     #新的索引名字
 }
}

具体操作参考这里 https://blog.youkuaiyun.com/qq_30502699/article/details/104394973


  1. 过滤(查询后过滤)
GET /movie_index/movie/_search
{
  "query": {
    "match": {
      "name": "red"
    }
  },
  "post_filter": {
    "term": {
      "actorList.id": "3"
    }
  }
}

  1. 查询前过滤(推荐使用)
GET movie_index/movie/_search
{
  "query": {
    "bool": {
      "filter": [
        {"term": 
          {"actorList.id": 3}
        },
        {
          "term":
            {"actorList.id": 1}
        }
      ],
      "must": 
        {"match": {
          "name": "zhang"
        }}
      
    }
  }
}

  1. 按范围过滤
GET movie_index/movie/_search
{
  "query": {
    "bool": {
      "filter": {
        "range": {
          "doubanScore": {
            "gt": 5,
            "lt": 9
          }
        }
      }
    }
  }
}

gt : 大于
lt : 小于
gte : 大于等于
lte : 小于等于


  1. 排序
GET movie_index/movie/_search
{
  "query":{
    "match": {"name":"red operation"}
  }
  , "sort": [
    {
      "doubanScore": {
        "order": "desc"
      }
    }
  ]
}

  1. 分页查询
GET movie_index/movie/_search
{
  "query": { "match_all": {} },
  "from": 1,
  "size": 1
}

  1. 指定查询的字段
GET movie_index/movie/_search
{
  "query": { "match_all": {} },
  "_source": ["name", "doubanScore"]
}

  1. 聚合
//每个演员参演了多少部电影
GET movie_index/movie/_search
{
  "aggs": {
    "groupby_actor": {
      "terms": {
        "field": "actorList.name.keyword"
      }
    }
  }
}

//每个演员参演电影的平均分是多少,并按评分排序
GET movie_index/movie/_search
{ 
  "aggs": {
    "groupby_actor_id": {
      "terms": {
        "field": "actorList.name.keyword" ,
        "order": {
          "avg_score": "desc"
          }
      },
      "aggs": {
        "avg_score":{
          "avg": {
            "field": "doubanScore" 
          }
        }
       }
    } 
  }
}

  1. 修改 document

修改分两种: 整体替换和只修改某个字段
整体替换和新增文档没有区别

//整体替换
PUT /movie_index/movie/3
{
  "id":"3",
  "name":"incident red sea",
  "doubanScore":"8.0",
  "actorList":[  
    {"id":"1","name":"zhang chen"}
  ]
}

//只修改某个字段(使用post方法)
POST /movie_index/movie/3/_update
{
  "doc": {
    "doubanScore":"8.1"
  }
}

六.elasticsearch分词

 es是自带中文分词的,但是它默认不懂中文,没有词语的概念,如:默认分词分出来的是这样 :
“这茶叶比较贵”,
“这”,“茶”,“叶”,“比”,“较”,“贵”,
这种分法明显是不符合我们的需求的,我们希望得到
“这茶叶比较贵”,
“这”,“茶叶”,“比较”,“贵”,
所以我们要安装中文分词器。


 在elasticsearch的目录下面,有一个叫plugins的目录,es会在这个目录里面扫描,里面的每一个目录都被认为是一个分词插件。

安装IK分词器

  1. 在plugins目录下创建目录 IK;
  2. 去github下载对应自己es版本的IK(目录名随意起),版本一定要和自己的es版本对应!https://github.com/medcl/elasticsearch-analysis-ik/releases
  3. 把下载的包里面的文件复制到刚刚创建的IK目录里面;
  4. 重启es;
  5. 验证是否成功
GET _analyze
{
  "analyzer": "ik_smart", 			
  "text":"这茶叶比较贵"
}

ik分词器主要是两个:
ik_smart : 简单分词器,将以最小的组合拆分中文。
ik_max_word : 最大化分词器,以多结果方式拆分中文。
操作正常的话,会返回这样的数据, 就是我们想要的结果。

{
  "tokens" : [
    {
      "token" : "这",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "CN_CHAR",
      "position" : 0
    },
    {
      "token" : "茶叶",
      "start_offset" : 1,
      "end_offset" : 3,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "比较",
      "start_offset" : 3,
      "end_offset" : 5,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "贵",
      "start_offset" : 5,
      "end_offset" : 6,
      "type" : "CN_CHAR",
      "position" : 3
    }
  ]
}

七.通过mapping指定字段属性

  1. 先看一下类型的对应关系:
true/false → boolean
1020  →  long
20.1 → double
“2018-02-01” → date
“hello world” → text

分词和索引
1.索引  默认都建索引
2.分词  text  

八.安装logstash

首先电脑java的版本得在1.8以上;
然后去官网下载logstash包,https://www.elastic.co/cn/downloads/logstash
一个java项目,不需要安装,直接解压执行即可。
测试logstash

  • 解压logstash包之后,进入目录logstash-7.9.3/bin;(我下载的是7.9.3版本)
  • 执行 .logstash -e ‘input { stdin { } } output { stdout {} }’
  • 随便输入一个啥,比如hello,如果返回
{
    "@timestamp" => 2020-11-06T12:31:13.266Z,
       "message" => "hello",
          "host" => "V_VZJYAN-MB0",
      "@version" => "1"
}

那么说明可以用了。

九.使用logstash把mysql数据导入es

这里面坑真心多,一点一点来

  • 下载最新的 logstash-integration-jdbc 包,https://github.com/logstash-plugins/logstash-integration-jdbc。我的logstash版本是7.9.3, 其他版本可能有出入
  • 解压安装包,进入logstash-integration-jdbc包里面,编译得到gem文件
    gem build logstash-integration-jdbc.gemspec
  • 把上面步骤得到的gem文件复制到 logstash 包的bin目录下, 安装最新的logstash-integration-jdbc。
    ./logstash-plugin install logstash-integration-jdbc-5.0.6.gem
    windows的同学执行./logstash-plugin.bat
  • logstash是ruby写的,所以还得安装ruby… 链接https://www.jianshu.com/p/c073e6fc01f5
  • 然后下载安装mysql驱动包 mysql-connector-java-5.1.45.jar。或者其他版本,自行下载…
  • 进入logstash包的bin目录下,创建编写两个文件:
  1. to_mysql.sql
select * from employee;		//sql语句自己写
  1. to_mysql.conf

input {
      stdin {
       }
      jdbc {
        # 数据库地址  端口  数据库名
        jdbc_connection_string => "jdbc:mysql://localhost:3306/companydb?characterEncoding=UTF-8&useSSL=false"
        # 数据库用户名
        jdbc_user => "root"
        # 数据库密码
        jdbc_password => "*******"
        # mysql java驱动地址 
        jdbc_driver_library => "/Users/afafa/Desktop/soft/mysql-connector-java-5.1.45.jar"
        jdbc_driver_class => "com.mysql.jdbc.Driver"
        jdbc_paging_enabled => "true"
        jdbc_page_size => "50000"
        # sql 语句文件路径
        statement_filepath => "/Users/afafa/Desktop/soft/logstash-7.9.3/bin/to_mysql.sql"
        # 定时字段 各字段含义(由左至右)分、时、天、月、年,全部为*默认含义为每分钟都更新
        schedule => "* * * * *"
     }
 }

filter {
    json {
        source => "message"
        remove_field => ["message"]
    }
}

output {
    elasticsearch {
        hosts => ["127.0.0.1:9200"]
        # index名称
        index => "companydb"
        # type名称
        document_type => "employee"
        # 文档_id
        document_id => "%{id}"
    }
    stdout {
        codec => json_lines
    }
}
  • 然后进入logstash包的bin目录下执行
    ./logstash -f to_mysql.conf,稍等片刻,没有报错的的话就可以去es里面查看数据了…
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值