ElasticSearch搜索涨芝士啦

ElasticSearch相关

ElasticSearch的简单了解

  1. 简介 : Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。Elasticsearch用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。官方客户端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和许多其他语言中都是可用的。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr,也是基于Lucene。
  2. 下载: https://www.elastic.co/cn/
  3. 特点 :
    1. 分布式,无需人工搭建集群(solr就需要人为配置,使用Zookeeper作为注册中心)
    2. Restful风格,一切API都遵循Rest原则,容易上手
    3. 近实时搜索,数据更新在Elasticsearch中几乎是完全同步的。

Linux下的安装和配置

  1. 在虚拟机上新建一个用户,因为ElasticSearch认为使用root有安全风险.
    1. 新建用户

      groupadd es
      useradd Es -g es
      chown -R Es:es /home/Es/
      
    2. 设置密码

      passwd Es
      
  2. 上传ES压缩包(使用SecureCRT工具上传,可传送到另一篇博客查看使用方法)
    1. 可从官网下载压缩包
    2. 百度网盘链接 : ES压缩包
    3. 提取码: md75
  3. 解压
    1. tar -xvf elasticsearch-6.2.4.tar.gz # 解压缩
    2. mv elasticsearch-6.2.4.tar.gz elasticsearch # 给他起个简单点的名字
    3. rm -rf elasticsearch-6.2.4.tar.gz # 顺便把压缩包给删除啦
  4. 修改配置
    1. 修改jvm.options,为的是减少内存占用
      1. cd ./elasticsearch/config
      2. vim jvm.options
      3. -Xms512m
        -Xmx512m
    2. 修改elasticsearch.yml,为的是把数据和日志记录的位置自定义
      1. path.data: /home/Es/elasticsearch/data # 数据目录位置
        path.logs: /home/Es/elasticsearch/logs # 日志目录位置
      2. 修改绑定的ip: network.host: 0.0.0.0 # 绑定到0.0.0.0,允许任何ip来访问
      3. bootstrap.system_call_filter: false # 在elasticsearch.yml 底部加上这句脚本,禁止bootstrap插件
      4. 因为没有data目录,自己创建一个
      5. cd /home/Es/elasticsearch/
      6. mkdir data
    3. 其它配置
      1. 权限问题
        1. 登录root用户 su - root

        2. vim /etc/security/limits.conf

        3. 添加内容 :

          * soft nofile 65536
          * hard nofile 131072
          * soft nproc 4096
          * hard nproc 4096
          
      2. 线程数问题
        1. vim /etc/security/limits.d/90-nproc.conf
        2. 加上这句话* soft nproc 4096
      3. 进程虚拟内存问题
        1. vim /etc/sysctl.conf
        2. 添加内容
          vm.max_map_count=655360
      4. sysctl -p
    4. 切换Es用户
      1. su Es 并进入bin目录
      2. ./elasticsearch
  5. 其它异常问题:
    1. jvm HotSpot client VM 与 server VM JVM is using the client VM [Java HotSpot™ Client VM] but should be using a server VM for the best performance.
      1. 修改文件 : JAVA_HOME\jre\lib\i386\jvm.cfg

        -server KNOWN      
        -client IF_SERVER_CLASS -server
        -minimal KNOW
        
    2. unable to load JNA native support library, native methods will be disable
      请参考另一篇博客: https://blog.csdn.net/zwq56693/article/details/107798089
    3. 启动成功,无法访问.
      1. linux开启9200和9300端口
      2. /sbin/iptables -I INPUT -p tcp --dport 9200 -j ACCEPT;
        /etc/rc.d/init.d/iptables save;
  6. 登录界面
    ElasticSearch搜索涨芝士啦_第1张图片

kibana

  1. 简介
    1. Kibana是一个基于Node.js的Elasticsearch索引库数据统计工具,可以利用Elasticsearch的聚合功能,生成各种图表,如柱形图,线状图,饼图等。
      而且还提供了操作Elasticsearch索引数据的控制台,并且提供了一定的API提示,非常有利于我们学习Elasticsearch的语法。
  2. 安装
    1. 下载 : https://www.elastic.co/cn/kibana
  3. 配置运行
    1. 进入安装目录下的config目录,修改kibana.yml文件:
      elasticsearch.url: “http://192.168.0.155:9200” # 修改elasticsearch服务器的地址
  4. 启动 :
    1. 进入安装目录下的bin目录:双击kibana.bat
  5. 访问 : http://127.0.0.1:5601
  6. kibanay页面ElasticSearch搜索涨芝士啦_第2张图片

ElasticSearch的使用

  1. IK分词器
    1. 安装ik分词器(功能是支持中文分词)

      1. 把ik分词器的jar放到Es的plugin目录下
      2. 解压 # unzip
      3. 把压缩包删除 # rm -rf xxx
      4. 重启Es
    2. 分词效果

      POST _analyze
      {
        "analyzer": "ik_smart"
        , "text": "我是中国人"
      }
      
      {
        "tokens": [
          {
            "token": "我",
            "start_offset": 0,
            "end_offset": 1,
            "type": "CN_CHAR",
            "position": 0
          },
          {
            "token": "是",
            "start_offset": 1,
            "end_offset": 2,
            "type": "CN_CHAR",
            "position": 1
          },
          {
            "token": "中国人",
            "start_offset": 2,
            "end_offset": 5,
            "type": "CN_WORD",
            "position": 2
          }
        ]
      }
      
  2. 操作索引
    1. 概念 :Elasticsearch也是基于Lucene的全文检索库,本质也是存储数据,很多概念与MySQL类似的。

      1. 索引(indices)----------------Databases 数据库
      2. 类型(type)--------------------Table 数据表
      3. 文档(Document)------------Row 行
      4. 字段(Field)-------------------Columns 列
    2. 概念详细解释

      1. 索引库(indices) : indices是index的复数,代表许多的索引,
      2. 类型(type) : 类型是模拟mysql中的table概念,一个索引库下可以有不同类型的索引,比如商品索引.
      3. 文档(document): 存入索引库原始的数据。比如每一条商品信息,就是一个文档
      4. 字段(field): 文档中的属性
      5. 映射配置(mappings): 字段的数据类型、属性、是否索引、是否存储等特性
      6. 索引集(Indices,index的复数):逻辑上的完整索引
      7. 分片(shard):数据拆分后的各个部分
      8. 副本(replica):每个分片的复制
    3. 创建索引

      1. PUT请求 索引名称(小写字母) 分片个数 副本个数

        PUT es
        {
          "settings": {
            "number_of_shards": 1,
            "number_of_replicas": 1
          }
        }
        
        {
          "acknowledged": true,
          "shards_acknowledged": true,
          "index": "es"
        }
        
    4. 查看索引设置

      GET es
      
      {
        "es": {
          "aliases": {},
          "mappings": {},
          "settings": {
            "index": {
              "creation_date": "1596506579933",
              "number_of_shards": "1",
              "number_of_replicas": "1",
              "uuid": "BGMEzq0nS9WU7-c9tutqhw",
              "version": {
                "created": "6020499"
              },
              "provided_name": "es"
            }
          }
        }
      }
      
    5. 映射配置

      1. 映射是定义文档的过程,文档包含哪些字段,这些字段是否保存,是否索引,是否分词等

        PUT es/_mapping/goods
        {
          "properties":
          {
            "title": 
            {
              "type": "text",
              "analyzer": "ik_max_word"
            },
            "images": 
            {
              "type": "keyword",
              "index": "false"
            },
            "price": 
            {
            "type": "float"
            }
          }
        }
        
    6. 查看映射 : GET /索引库名/_mapping

      GET es/_mapping/
      
    7. 字段属性详解

      1. String类型
        1. text:可分词,不可参与聚合
        2. keyword:不可分词,数据会作为完整字段进行匹配,可以参与聚合
      2. Numerical:数值类型
        1. 基本数据类型:long、interger、short、byte、double、float、half_float
        2. 浮点数的高精度类型:scaled_float 需要指定一个精度因子,比如10或100。elasticsearch会把真实值乘以这个因子后存储,取出时再还原。
      3. Date:日期类型
        1. elasticsearch可以对日期格式化为字符串存储,但是建议我们存储为毫秒值,存储为long,节省空间。
      4. .index
        1. true:字段会被索引,则可以用来进行搜索。默认值就是true
        2. false:字段不会被索引,不能用来搜索
        3. index的默认值就是true,也就是说你不进行任何配置,所有字段都会被索引。
      5. store
        1. 是否将数据进行额外存储。
      6. boost
        1. 激励因子

ElasticSearch的简单的CRUD

  1. 新增数据
    1. 随机id值

      POST /索引库名/类型名
      {
      "key":"value"
      }
      ------------------
      POST /es/goods
      {
        "title":"rongyao手机",
        "images":"http://image.junyang.com/12479122.jpg",
        "price":2699.00
      
      }
      {
        "_index": "es",
        "_type": "goods",
        "_id": "undEwHMB4sJhf15MpqCs",
        "_version": 1,
        "result": "created",
        "_shards": {
          "total": 2,
          "successful": 1,
          "failed": 0
        },
        "_seq_no": 0,
        "_primary_term": 2
      }
      
    2. 自定义id值

      POST /索引库名/类型/id值
      {
      ...
      }
      
  2. 修改数据: 需要根据id进行修改
    1. id对应文档存在,则修改

    2. id对应文档不存在,则新增

    3. 没有定义映射时,也可以添加数据

      PUT /es/goods/undEwHMB4sJhf15MpqCs
      {
      	"title":"小米手机",
      	"images":"http://image.es.com/12479122.jpg",
      	"price":3899.00,
      	"stock": 100,
      	"saleable":true
      }
      
  3. 删除数据
    1. DELETE /索引库名/类型名/id值
  4. 查询
    1. 基本语法

      GET /索引库名/_search
      {
      	"query":{
      	"查询类型":{
      	"查询条件":"查询条件值"
      	}
      	}
      }
      
    2. 查询所有(match_all)

      1. query : 代表查询对象
      2. match_all : 代表查询所有
      GET /es/_search
      {
      	"query":{
      	"match_all": {}
      	}
      }
      
      1. 查询结果

        took:查询花费时间,单位是毫秒
        time_out:是否超时
        _shards:分片信息
        hits:搜索结果总览对象
        	total:搜索到的总条数
        	max_score:所有结果中文档得分的最高分
        	hits:搜索结果的文档对象数组,每个元素是一条搜索到的文档信息
        		_index:索引库
        		_type:文档类型
        		_id:文档id
        		_score:文档得分
        		_source:文档的源数据
        
      2. 匹配查询(match)

        1. 首先进行分词,分为’小米’,‘曲面’,‘电视’.
        2. “minimum_should_match”: “75%” : 意思是只要匹配到
          总词条数量的75%即可,这里3*75% 约等于2。所以只要包含2个词条就算满足条件
        GET /es/_search
        {
        	"query":{
        		"match":{
        			"title":{
        			"query":"小米曲面电视",
        			"minimum_should_match": "75%"
        			}
        		}
        	}
        }
        
      3. 多字段查询(multi_match)

        1. multi_match与match类似,不同的是它可以在多个字段中查询

        2. 会在title字段和subtitle字段中查询荣耀这个词

          GET /es/_search
          {
          	"query":{
          		`"multi_match": {
          			"query": "荣耀",
          			"fields": [ "title", "subTitle" ]
          		}
          	}
          }
          ``
          
      4. 词条匹配(term)

        1. term查询被用于精确值 匹配,这些精确值可能是数字、时间、布尔或者那些未分词的字符串

          GET /es/_search
          {
          	"query":{
          		"term":{
          			"price":2699.00
          		}
          	}
          }
          
      5. 多词条精确匹配(terms)

        1. terms 查询和 term 查询一样,但它允许你指定多值进行匹配。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件

          GET /es/_search
          {
          	"query":{
          		"terms":{
          			"price":[2699.00,2899.00,3899.00]
          		}
          	}
          }
          
      6. 结果过滤

        1. 直接指定字段

        2. 显示title和price

          GET /es/_search
          {
          	"_source": ["title","price"],
          		"query": {
          			"term": {
          			"price": 2699
          		}
          	}
          }
          
      7. 指定includes和excludes

        1. includes:来指定想要显示的字段

        2. excludes:来指定不想要显示的字段

          GET /es/_search
          {
          	"_source": {
          	"includes":["title","price"]
          	},
          	"query": {
          		"term": {
          			"price": 2699
          		}
          	}
          }
          

ElasticSearch的高级查询

  1. 布尔组合(bool)

    1. bool把各种其它查询通过must(与)、must_not(非)、should(或)的方式进行组合

      GET /es/_search
      {
      	"query":{
      		"bool":{
      			"must": { "match": { "title": "荣耀" }},
      			"must_not": { "match": { "title": "电视" }},
      			"should": { "match": { "title": "手机" }}
      		}
      	}
      }
      
  2. 范围查询(range)

    1. range 查询找出那些落在指定区间内的数字或者时间

      GET /es/_search
      {
      	"query":{
      		"range": {
      			"price": {
      			"gte": 1000.0,
      			"lt": 2800.00
      		}
      	}
      }
      
  3. 模糊查询(fuzzy)

    1. fuzziness:指定允许的编辑距离
    GET /es/_search
    {
    	"query": {
    		"fuzzy": {
    			"title": {
    				"value":"appla",
    				"fuzziness":1
    			}
    		}
    	}
    }
    
  4. 过滤(filter)

    1. filter : 跟过滤条件

      GET /es/_search
      {
      		"query":{
      				"bool":{
      					"must":{ "match": { "title": "小米手机" }},
      					"filter":{
      					"range":{"price":{"gt":2000.00,"lt":3800.00}}
      				}
      			}
      		}
      }
      
  5. 排序
    1. 单字段排序 : sort 可以让我们按照不同的字段进行排序,并且通过order指定排序的方式

    GET /es/_search
    {
    	"query": {
    		"match": {
    			"title": "小米手机"
    				}
    		},
    		"sort": [
    				{
    					"price": {
    					"order": "desc"
    					}
    				}
    			]
    		}
    }
    
  6. 多字段排序

    GET /goods/_search
    {
    	"query":{
    			"bool":{
    				"must":{ "match": { "title": "小米手机" }},
    				"filter":{
    					"range":{"price":{"gt":200000,"lt":300000}}
    				}
    			}
    		},
    		"sort": [
    			{ "price": { "order": "desc" }},
    			{ "_score": { "order": "desc" }}
    		]
    }
    
  7. 聚合aggregations

    1. 基本概念

      1. 桶(bucket) : 桶的作用,是按照某种方式对数据进行分组,每一组数据在ES中称为一个桶,例如我们根据国籍对人划分,可以得到中国桶、英国桶,日本桶……或者
        我们按照年龄段对人进行划分:010,1020,2030,3040等。
      2. 度量(metrics) : 分组完成以后,我们一般会对组中的数据进行聚合运算,例如求平均值、最大、最小、求和等,这些在ES中称为度量
    2. 创建索引:

      PUT /cars
      {
        "settings": {
          "number_of_shards": 1,
          "number_of_replicas": 0
          },
          "mappings": {
              "transactions": {
                "properties": {
                  "color": {
                    "type": "keyword"
                    },
                  "make": {
                    "type": "keyword"
                  }
                  }
              }
          }
      }		
      
    3. 导入数据

      POST /cars/transactions/_bulk
      { "index": {}}
      { "price" : 10000, "color" : "red", "make" : "honda", "sold" : "2014-10-28" }
      { "index": {}}
      { "price" : 20000, "color" : "red", "make" : "honda", "sold" : "2014-11-05" }
      { "index": {}}
      { "price" : 30000, "color" : "green", "make" : "ford", "sold" : "2014-05-18" }
      { "index": {}}
      { "price" : 15000, "color" : "blue", "make" : "toyota", "sold" : "2014-07-02" }
      { "index": {}}
      { "price" : 12000, "color" : "green", "make" : "toyota", "sold" : "2014-08-19" }
      { "index": {}}
      { "price" : 20000, "color" : "red", "make" : "honda", "sold" : "2014-11-05" }
      { "index": {}}
      { "price" : 80000, "color" : "red", "make" : "bmw", "sold" : "2014-01-01" }
      { "index": {}}
      { "price" : 25000, "color" : "blue", "make" : "ford", "sold" : "2014-02-12" }
      
    4. 聚合为桶

      1. 我们按照汽车的颜色color来划分桶

      2. size : 查询条数,这里设置为0,因为我们不关心搜索到的数据,只关心聚合结果,提高效率

      3. aggs:声明这是一个聚合查询,是aggregations的缩写

        1. popular_colors:给这次聚合起一个名字,任意。
          1. terms:划分桶的方式,这里是根据词条划分
            1. field:划分桶的字段
        GET /cars/_search
        {
          "size" : 0,
          "aggs" : {
          "popular_colors" : {
            "terms" : {
              "field" : "color"
              }
            }
          }
        }
        
    5. 桶内度量

      1. 求价格平均值的度量

        1. aggs:我们在上一个aggs(popular_colors)中添加新的aggs。可见度量也是一个聚合,度量是在桶内的聚合
        2. avg_price:聚合的名称
        3. avg:度量的类型,这里是求平均值
        4. field:度量运算的字段
        GET /cars/_search
        {
        "size" : 0,
        "aggs" : {
          "popular_colors" : {
            "terms" : {
              "field" : "color"
              },
            "aggs":{
              "avg_price": {
                "avg": {
                 "field": "price"
                }
              }
            }
            }
          }
        }
        
    6. 桶内嵌套桶

      1. 统计每种颜色的汽车中,分别属于哪个制造商,按照make字段再进行分桶

        1. maker:在嵌套的aggs下新添一个桶,叫做maker
        2. terms:桶的划分类型依然是词条
        3. filed:这里根据make字段进行划分
        GET /cars/_search
        {
        "size" : 0,
        "aggs" : {
            "popular_colors" : {
              "terms" : {
                "field" : "color"
              },
              "aggs":{
                "avg_price": {
                  "avg": {
                    "field": "price"
                  }
                },
                "maker":{
                  "terms":{
                   "field":"make"
                  }
                }
              }
            }
          }
        }
        
        
    7. 阶梯分桶Histogram

      1. histogram是把数值类型的字段,按照一定的阶梯大小进行分组。你需要指定一个阶梯值(interval)来划分阶梯大小。

      2. 比如你有价格字段,如果你设定interval的值为200,那么阶梯就会是这样的:0,200,400,600,…

      3. 我们对汽车的价格进行分组,指定间隔interval为5000:

      4. min_doc_count为1,来约束最少文档数量为1,这样文档数量为0的桶会被过滤

        GET /cars/_search
        {
          "size":0,
          "aggs":{
            "price":{
              "histogram": {
                "field": "price",
                "interval": 5000,
                "min_doc_count": 1
              }
            }
          }
        }
        

通过Java操作ElasticSearchJava操作Es小Demo

你可能感兴趣的:(笔记,搜索引擎,elasticsearch,java)