ElasticSearch 入门详解

一. 简介

Elasticsearch是一个基于Apache Lucene(TM)的开源搜索引擎。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。

但是,Lucene只是一个库。想要使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。

Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。

Elasticsearch的中文网址:https://www.elastic.co/cn/products/elasticsearch

1.1 正向索引与倒排索引

正向索引与倒排索引,这是在搜索领域中非常重要的两个名词,正向索引通常用于数据库中,在搜索引擎领域使用的最多的就是倒排索引,我们根据如下两个网页来对这两个概念进行阐述:

html1

我爱我的祖国,我爱编程

html2:

我爱编程,我是个快乐的小码农

正向索引:  假设我们使用mysql的全文检索,会对如上两句话分别进行分词处理,那么预计得到的结果如下:

我 爱 爱我 祖国 我的祖国 编程 爱编程 我爱编程
我 我爱 爱 编程 爱编程 我爱编程 快乐 码农 小码农

假设我们现

在使用正向索引搜索 编程 这个词,那么会到第一句话中去查找是否包含有 编程 这个关键词,如果有则加入到结果集中;第二句话也是如此。假设现在有成千上百个网页,每个网页非常非常的分词,那么搜索的效率将会非常非常低些。

倒排索引:  倒排索引是按照分词与文档进行映射,我们来看看如果按照倒排索引的效果:

关键词文档名
html1,html2
html1,html2
爱我 html1
我爱 html2
祖国 html1
我的祖国 html1
编程 html1,html2
我爱编程 html1,html2
爱编程 html1,html2
快乐 html2
码农 html2
小码农 html2

如果采用倒排索引的方式搜索 编程 这个词,那么会直接找到关键词中查找到 编程 ,然后查找到对应的文档,这就是所谓的倒排索引。

1.2 Elasticsearch概念以及产品

Elasticsearch中的索引的概念与数据库中索引的概念是完全不一样的,Elasticsearch中索引如果类比到数据库,那就是一个数据库名。

文档在Elasticsearch中就是具体的数据,类比到数据库中那就是一条记录。

二. Elasticsearch环境搭建

下载地址:https://www.elastic.co/cn/start,在下载页面我们需要下载 Elasticsearch和Kibana.

2.1 Elasticsearch的安装

2.1.1 单机版安装

下载后解压进入到bin目录下,双击elasticsearch.bat,即可启动。在浏览器输入:http://localhost:9200/ 是否安装成功,如下图所示:

 

2.1.2 集群安装

Elasticsearch集群的安装非常的简单,只需要作一些简单的配置,修改配置文件 config/elasticsearch.yml。

本节将采用两台节点来配置集群,一台是Windows操作系统,另外一台是Linux操作系统,将Windows操作系统下的Elasticsearch节点作为主节点。两台服务器的IP地址如下:

操作系统IP节点类型
Windows操作系统 192.168.43.240 主节点(master)
Linux操作系统 192.168.223.139 从节点(Slave)

主节点

  1. 修改C:\Windows\System32\drivers\etc\hosts文件,加入如下内容

192.168.43.240  master
  1. 修改Elasticsearch的config目录下的elasticsearch.yml文件,内容如下:

# 集群的名字
cluster.name: my-application
# 节点的名称
node.name: master
# 数据存放的位置
path.data: D:/elasticsearch-datas/to/data
# 日志存放的位置
path.logs: D:/elasticsearch-datas/to/logs
# 节点绑定的IP
network.host: 192.168.43.240
# 设置端口号
http.port: 9200
# 集群中所有的节点的ip地址
discovery.seed_hosts: ["192.168.43.240", "192.168.223.139"]
# 初始状态下集群中主节点的 node.name
cluster.initial_master_nodes: ["master"]
  1. 启动elasticsearch

从节点

  1. 创建elasticsearch用户,执行如下命令

useradd -m -s /bin/bash elasticsearch
  1. 给elasticsearch的主目录权限授予新创建的 elasticsearch 用户

chown -R elasticsearch /elasticsearch/
  1. 在 /etc/sysctl.conf 文件中加入如下内容

vm.max_map_count=262144  #加大虚拟内存空间,然后重启服务器

如果报以下错误,

max number of threads [3604] for user [elasticsearch] is too low, increase to at least [4096]

解决方案:修改 /etc/security/limits.conf 文件,在文件中加入如下内容:

*      soft     nproc 4096
*     hard     nproc 4096
  1. 在/etc/hosts目录下加入如下内容

192.168.43.240  master
  1. 修改Elasticsearch的config目录下的elasticsearch.yml文件,内容如下:

# 集群的名字
cluster.name: my-application
# 节点的名称
node.name: slave1
# 数据存放的位置
path.data: /elasticsearch-datas/to/data
# 日志存放的位置
path.logs: /elasticsearch-datas/to/logs
# 节点绑定的IP
network.host: 192.168.223.139
# 设置端口号
http.port: 9200
# 集群中所有的节点的ip地址
discovery.seed_hosts: ["192.168.43.240", "192.168.223.139"]
# 初始状态下集群中主节点的 node.name
cluster.initial_master_nodes: ["master"]
  1. 切换到elasticsearch用户,进入到elasticsearch的家目录下,执行如下命令:

    su - elasticsearch #切换用户
    bin/elasticsearch #启动elasticsearch

 

集群监控

下载地址:https://github.com/lmenezes/cerebro/releases

直接双击cerebro家目录下的bin目录下的 cerebro.bat 即可启动,在浏览器地址栏访问:localhost:9000

 

在Node address输入:http://192.168.43.240:9200,然后点击 Connect 按钮

 

 

2.2 Kibana的安装

Kibana是世界上最受欢迎的开源日志分析平台ELK Stack中的“K” ,它为用户提供了一个工具,用于在存储于Elasticsearch集群中的日志数据进行检索,可视化和构建仪表板。

Kibana的核心功能是数据查询和分析。使用各种方法,用户可以搜索Elasticsearch中索引的数据,以查找其数据中的特定事件或字符串,以进行根本原因分析和诊断。基于这些查询,用户可以使用Kibana的可视化功能,允许用户使用图表,表格,地理图和其他类型的可视化以各种不同的方式可视化数据。

A. 下载后进入到家目录下的bin目录中,首先修改config目录下的kibana.yml文件,修改如下内容:

elasticsearch.hosts: ["http://192.168.43.240:9200", "http://192.168.223.139:9200"]

B. 进入bin目录下,双加 kibana.bat文件,在浏览器地址栏访问:http://localhost:5601

 

 

 

C. Kibana中我们使用最多的就是 Dev Tools工具,来进行所有命令的演示:

注:如上 GET _cat/indices 命令是查看所有的索引。

2.3 Logstash的安装

Logstash是一个开源的服务器端数据处理管道,可以同时从多个数据源获取数据,并对其进行转换,然后将其发送到你最喜欢的“存储”。创建于2009年,于2013年被elasticsearch收购。

 

Logstash的下载地址:https://www.elastic.co/cn/downloads/logstash

A.下载测试数据集,下载地址:http://files.grouplens.org/datasets/movielens/,在该网页中下载ml-latest.zip

 

 

下载后解压目录,将movies.csv文件拷贝到指定的目录下,例如:D:/logstash-datas/ 目录。

B. 进入到Logstash的解压目录,进入到config目录下,新建logstash.conf,文件内容如下:

input {
file {
  path => "D:/logstash-datas/movies.csv"
  start_position => "beginning"
  sincedb_path => "D:/logstash-datas/db_path.log"
}
}
filter {
csv {
  separator => ","
  columns => ["id","content","genre"]
}

mutate {
  split => { "genre" => "|" }
  remove_field => ["path", "host","@timestamp","message"]
}

mutate {

  split => ["content", "("]
  add_field => { "title" => "%{[content][0]}"}
  add_field => { "year" => "%{[content][1]}"}
}

mutate {
  convert => {
    "year" => "integer"
  }
  strip => ["title"]
  remove_field => ["path", "host","@timestamp","message","content"]
}

}
output {
  elasticsearch {
    hosts => "http://192.168.31.173:9200"
    index => "movies"
    document_id => "%{id}"
  }
stdout {}
}

C. 在命令行进入到logstash的bin目录下,输入如下命令启动Logstash:

logstash.bat -f D:\logstash-datas\config\logstash.conf

特别强调:路径中绝对不能有中文。

D. 在Kibana的Dev Tools中执行 GET _cat/indices, 即可查看到movies数据集

三. Elasticsearch的基本概念

3.1 索引、文档、类型

索引

Elasticsearch中的索引有多层的意思:a. 某一类文档的集合就构成了一个索引,类比到数据库就是一个数据库(或者数据库表);b.它还描述了一个动作,就是将某个文档保存在elasticsearch的过程也叫索引;c. 倒排索引。

文档

具体的一条数据,类比到数据库就是一条记录。

类型

在7.0之前,一个Index可以创建多个类型,从7.0开始,一个索引只能创建一个类型,也就是_doc

DBMSElasticsearch
Table Index(Type)
Row Document
Column Field
Schema Mapping
SQL DSL(Descriptor Structure Language)

四. RestAPI

查询所有的索引

GET _cat/indices

查询movies的信息

GET movies

查询movies的记录总数

GET movies/_count

查询movies的前几条数据

GET movies/_search

4.1 基本CRUD

A. 添加数据,没有指定ID, 系统会生成ID

POST user/_doc
{
 "age": 10,
 "firstName": "Will",
 "lastName": "Smith"
}

B. 操作数据,指定ID,如果有对应的ID,就修改数据;如果没有对应的ID,就添加数据

POST user/_doc/1
{
 "age": 20,
 "firstName": "Roden",
 "lastName": "Jhson"
}

C. 通过 _create 的方式,如果存在ID,就会报错

POST user/_create/2
{
 "age": 40,
 "firstName": "Douge",
 "lastName": "Lee"
}

PUT users/_create/8
{
 "age": 50,
 "firstName":"Jacks",
 "lastName": "Lily"
}

D. 查询指定ID的文档

GET user/_doc/1

E. 删除指定ID的文档

DELETE user/_doc/2Gxqc24BJqcwPamzqWgn

F. 指定ID,创建或者覆盖

PUT user/_doc/1
{
 "age": 40,
 "firstName": "Hello",
 "lastName": "Lee"
}

G. 修改原有数据的结构

POST user/_update/1
{
 "doc": {
   "firstName":"Rodan",
   "lastName": "Johson"
}
}

H.批量查询

GET _mget
{
 "docs": [
  {"_index":"movies", "_id":"104372"},
  {"_index":"movies", "_id":"104374"}
]
}

I. 分页查询

GET movies/_search
{
 "from": 0,
 "size": 20
}

J. 批量插入(可以指定ID,也可以不指定ID)

POST user/_bulk
{"index":{"_id": 23}}
{"firstName":"Will", "lastName":"Smith", "mobile": "123455"}
{"index":{}}
{"firstName":"Lily", "lastName":"Bob", "mobile": "98765"}

4.2 URI查询

泛查询,就是不指定字段,全字段查找,如下查找所有字段中包含有2012的电影

GET movies/_search?q=2012

查询title中包含有2012的所有的电影(df是default field)

GET movies/_search?q=2012&df=title
或者
GET movies/_search?q=title:2012

查询title中包含有2012,取索引从10开始,共8条数据

GET movies/_search?q=title:2012&from=10&size=8

字符串判断查询:

# 查询titile中包含有Beautiful, Mind
GET movies/_search?q=title:Beautiful Mind

#查询title中包含有Beautiful, 并且年份大于2012
GET movies/_search?q=title:Beautiful AND year:>=2012

#查询titile中包含有Beautiful或者Mind
GET movies/_search?q=title:(Beautiful Mind)
GET movies/_search?q=title:(+Mind +Beautiful)

#查询title中包含有“Beautiful Mind”的所有的电影
GET movies/_search?q=title:"Beautiful Mind"


#查询title中既包含有Mind又包含有Beautiful的所有的电影,对先后顺序没有要求
GET movies/_search?q=title:(Mind AND Beautiful)
GET movies/_search?q=title:(+Mind AND +Beautiful)

#查询title中包含Mind但是不包含Beautiful的所有的电影
GET movies/_search?q=title:(Mind NOT Beautiful)
GET movies/_search?q=title:(Mind -Beautiful)

年份判断查询:

#查询2018年以后上映的电影
GET movies/_search?q=year:>=2018

#查询2012年到2017年上映的电影
GET movies/_search?q=year:(>=2012 AND <2018)

#查询2016年到2017年所有的电影,注意:必须以 ] 结尾
GET movies/_search?q=year:{2015 TO 2017]

正则判断查询:

#查询title中以Mi开头,中间包含一个字符,以d结尾的所有的电影
GET movies/_search?q=title:Mi?d

#查询title中以Min开头,后面为任何内容的电影
GET movies/_search?q=title:Min*

4.3 Request Body查询

在有些查询中,可能会用到各种特别复杂的查询,那么就需要使用Request Body查询。

A.以year的倒序排序,查询电影年份在 [2017, 2018]的数据, query只能单条件查询

GET movies/_search
{
"sort": [
{
"year": {
"order": "desc"
}
}
],
# query中只能有一个条件
"query": {
"range": {
"year": {
"gte": 2017,
"lte": 2018
}
}
}
}

 

B.以year的倒序排序,查询titile中包含有Beautiful或者Mind的数据, query只能单条件查询

GET movies/_search
{
"sort": [
{
"year": {
"order": "desc"
}
}
],
# query中只能有一个条件
"query": {
"match": {
"title": "Beautiful Mind"
}
}
}

 

C. 按照年份的倒序,分页查询

GET movies/_search
{
 "sort": [
  {
     "year": {
       "order": "desc"
    }
  }
],
 "from": 0,
 "size": 20
}

D. 短语匹配,查询title中包含有 “Beautiful Mind” 这个短语的的电影

GET movies/_search
{
 "query": {
   "match_phrase": {
     "title": "Beautiful Mind"
  }
}
}

E. 只查询部分列

GET movies/_search
{
 "_source": ["title", "year"]
}

F. 多个条件查询,多条件查询必须使用bool

GET movies/_search
{
 "query": {
   "bool": {
     "must": [
      {
         "range": {
           "year": {
             "gte": 2017,
             "lte": 2018
          }
        }
      },
      {
         "match": {
           "title": "Beautiful Mind"
        }
      }
    ]
  }
}
}

G. 多字段同时匹配某些字符串

GET movies/_search
{
 "query": {
   "multi_match": {
     "query": "beautiful mind Romance",
     "fields": ["title", "genre"],
     "type": "best_fields"
  }
}
}

其中type的值有三个:

  • most_fields:在多字段中匹配的越多排名越靠前

  • best_fields: 能完全匹配的文档,排名越靠前。

  • cross_fields: 查询越分散,排名越靠前。

H. query_string 的用法

GET movies/_search
{
 "query": {
   "query_string": {
     "default_field": "title",
     "query": "Beautiful Mind",
     "default_operator": "AND"   #不加默认是OR
  }
}
}
GET movies/_search
{
 "query": {
   "query_string": {
     "fields": ["title", "genre"],
     "query": "Beautiful Mind",
     "default_operator": "AND"
  }
}
}

I. term实现精准匹配,查询title为Beautiful Mind 的电影

GET movies/_search
{
 "query": {
   "term": {
     "title": {
       "value": "Beautiful Mind"
    }
  }
}
}

J. 多条件或者判断

GET movies/_search
{
 "query": {
   "bool": {
     "should": [
      {
         "match": {
           "title": "Beautiful Mind"
        }
      },
      {
         "range": {
           "year": {
             "gte": 2017,
             "lte": 2018
          }
        }
      }
    ]
  }
}
}

K. 推荐搜索

GET movies/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title": "beautifu Minx"
          }
        },
        {
          "match": {
            "genre": "drama"
          }
        }
      ]
    }
  },
  "suggest": {
    "title-suggest": {
      "text": "beautifu Minx",
      "term": {
        "field": "title",
        "suggest_mode": "missing"
      }
    },
    "genre-suggest": {
       "text": "drama",
      "term": {
        "field": "genre",
        "suggest_mode": "missing"
      }
    }
  }
}


所谓的推荐搜索就是当我们根据条件搜索的时候,因为单词的拼写错误,但是无法搜索出结果,那么Elasticsearch会给出一定的搜索建议,通过 sugguest 来实现。

我们说一下suggest_mode 的三种模式:missingpopularalways

missing:  意思是当词典中没有找到对应的索引信息,才去推荐。

popular:  意思是即使我们去搜索一个被索引了的单词,但是还是会去给我们推荐类似的但是出现频率很高的词。

always:  无论在任何情况下,都给出推荐。

4.5 自动补全功能

Elasticsearch的自动补全功能是基于 suggest 来实现的,但是需要提前定义好需要进行搜索字段的mapping信息(mapping一旦创建好后是不能修改的)。

A. 定义mapping并执行,需要自动补全的属性的 type 必须是 completion

{"mappings" : {
"properties" : {
"@version" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"genre" : {
"type" : "completion",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"id" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"title" : {
"type" : "completion",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"year" : {
"type" : "long"
}
}
}
}

posted @ 2020-02-07 23:13  MadnessLing  阅读(3)  评论(0)    收藏  举报