Elasticsearch 入门

2018-12-02  本文已影响0人  yangjingqzp

Elasticsearch 是一个分布式的、可扩展的、近实时的开源搜索分析引擎。它支持 PB 级的容量,在存储时通过对文档的分析和建立索引,使之可以被全文搜索、分析。它的底层基于开源库 Luceue 。Elasticsearch 对 Luceue 进行了封装并提供了 REST API 的操作接口,开箱即用。

基本概念

概念对比

学习新内容时,最容易的理解方式是用它和已经熟悉的概念进行比较。下面是 Elasticsearch 与 Mysql 对应概念的比较。

概念 Mysql Elasticsearch
Index 索引 数据库 一个逻辑上存储文档的地方,可以是集群
Type 类型 数据表 一个索引可以在逻辑上分为不同的类型。与 Mysql 不同之处在于一个索引中的不同类型的字段是相同的;而数据库中不同表的字段基本上是不同的。
Document 文档 数据行 一个文档对象所有的键和值,是 JSON 格式,比 Mysql 复杂,可以包含对象、数组
Mapping 映射 数据类型 除了描述文档中每个值的数据类型,还包括字段的 index(怎样索引字符串) , analyzer(指定搜索和索引时使用的分析器)
shard 主分片 一个分片是一个 Lucene 索引。一个 ES 索引的分片数是在创建索引的时候设置的,因为有了分片,ES 水平扩展时变得容易
replica 副本分片 类似从库 ES 的副本分片可以在创建时设置,在创建后修改

一个 Elasticsearch 服务的实例为一个节点,一个节点可以包含多个分片,至少需要包含一个分片。
Elasticsearch 的存储容量大小为所有的主分片容量决定。所以在创建索引的时候需要考虑分片预分配。默认为 5 个主分片,也就是最后水平可扩展最大的容量为 5 个 ES 服务实例。

对比例子

下面是使用 Mysql 创建一个雇员数据库和使用 Elasticsearch 创建一个雇员索引的比较。
雇员属性有:first_name、last_name、age、about (简介)

使用 Mysql 创建
  1. 创建数据库 megacorp 。
  2. 创建表 employee ,定义表的字段。设置字段的长度、类型,根据需要设置表的索引。
  3. 插入数据。
使用 Elasticsearch 创建
  1. 创建索引,创建时确定索引的分片数、副本分片数。如果不指定, ES 默认 5 分片、1 副本分片。
  2. 设置索引的 Mapping 。 比如 about 用 text 类型存储,age 用 long 类型。about 需要使用 ik-analyzer 中文分词器,这样就可以通过简介的内容搜索对应的雇员;而 age 设置为 not_analyzed (建立索引的时候,直接对 age 字段值建立索引,不会对内容进行分析,基本类型默认 date、long 默认为 not_analyzed)。
  3. 索引雇员文档到 Elasticsearch 中。

默认情况下,文档中每一个属性都会被索引,没有索引的属性是不能被搜索的。

Elasticsearch 集群搭建

使用 Docker-compose 可以让搭建 Elasticsearch 变得更简单。
集群文件目录如下:


Docker-compose 目录结构.png

docker-compose.yml 文档内容

version: '2.2'
services:
  elasticsearch:
    image: elasticsearch:6.5.1
    container_name: es
    environment:
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - ./es1/data:/usr/share/elasticsearch/data
      - ./es1/es.yml:/usr/share/elasticsearch/config/elasticsearch.yml
    ports:
      - 9200:9200
      - 9300:9300
    networks:
      - esnet
  elasticsearch2:
    image: elasticsearch:6.5.1
    container_name: es2
    environment:
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - ./es2/data:/usr/share/elasticsearch/data
      - ./es2/es.yml:/usr/share/elasticsearch/config/elasticsearch.yml
    networks:
      - esnet
  elasticsearch3:
    image: elasticsearch:6.5.1
    container_name: es3
    environment:
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - ./es3/data:/usr/share/elasticsearch/data
      - ./es3/es.yml:/usr/share/elasticsearch/config/elasticsearch.yml
    networks:
      - esnet

networks:
  esnet:

ES_JAVA_OPTS 设置 ES 使用的最大与最小 heap 空间。
主节点 es.yml

cluster.name: es-cluster
bootstrap.memory_lock: true
node.name: node-master
node.master: true
node.data: true

network.host: 0.0.0.0
http.port: 9200
transport.tcp.port: 9300
network.publish_host: es
transport.tcp.compress: true
discovery.zen.ping.unicast.hosts: ["es:9300", "es1:9300", "es3:9300"]

cluster.name 为 ES 集群名称,集群所有的节点必须是相同的名称。
bootstrap.memory_lock 用于锁定 ES 进程使用的内存地址,防止被 swap out
node.name 为节点的名称
node.master 是否为主节点
node.data 节点是否存储数据
http.port 为外部访问 ES 服务的端口
transport.tcp.port 为 ES 集群通信的端口
transport.tcp.compress 集群通信时进行压缩
discovery.zen.ping.unicast.hosts 单播发现。 ES 将在这里面的地址去通信发现集群节点
工作节点 es.yml

cluster.name: es-cluster
bootstrap.memory_lock: true
node.name: node-master-3
node.master: false
node.data: true

network.host: 0.0.0.0
http.port: 9200
transport.tcp.port: 9300
network.publish_host: es3
discovery.zen.ping.unicast.hosts: ["es:9300", "es2:9300", "es3:9300"]

工作节点与主节点主要是 node.master 的配置不同

docker-compose up

这样一个主节点、2个工作节点的 Elasticsearch 集群就搭建起来了。

结构化搜索实践

一个 Elasticsearch 的查询包含:

  1. 查询内容所在的索引、类型。 多个索引、多个类型之间使用“,”分割。
  2. 路由 routing 。如果数据建立索引的时候有指定路由,查询的时候可以指定路由,这样 ES 就不用到每个分片去查询一次了。
  3. 查询语句 query 。
  4. 排序。根据指定字段、排序方式进行排序。
  5. 分页。可以通过 from、limit 查询指定的数据。
    一个简单的 DSL SQL
curl -X GET "localhost:9200/bank/account/_search" -d '
{
    "query" : {
        "match": {
            "title" : "search"
        }
    },
    "from": 10,
    "size": 10,
    "sort": [
        {"date": {"order":"asc"}}
    ]
}'

bank 为查询的索引; account 为查询的类型;query 中为查询语句。

Elasticsearch 中的查询分为简单查询、组合查询。
常用的简单查询又分为了查询(query context)、过滤(filter context)。查询时不仅要找到匹配对应内容的文档,还会计算文档的分数(score), 过滤只需找到对应的文档,而不计算文档的分数。官方推荐能用过滤的地方就不要用查询。

简单查询
  1. match_all 和 match_none
    查询所有的内容
curl -X GET "localhost:9200/bank/_search" -d '
{
    "query" : {
        "match_all": {}
    }
}'
  1. 全文索引
    a. match 指定的分析器先对查询内容进行分析,然后对分析的内容在倒排索引中进行查询; match_phrase 也会先将搜索内容分析为词项,然后对词项进行搜索,但是匹配的数据需要包含所有的词项。
curl -X GET "localhost:9200/bank/account/_search" -d '
{
    "query" : {
        "match": {"title":"search"}
    }
}'

b. multi_match 通过对多个字段进行 match 搜索

curl -X GET "localhost:9200/bank/_search" -d '
{
    "query" : {
        "multi_match": {
            "query":"this is test",
            "fields": ["title", "subtitle"]
        }
    }
}'

c. query_string 通过查询语句进行查询
new york city 和 big apple 是两个独立的查询内容

curl -X GET "localhost:9200/bank/_search" -d '
{
    "query" : {
        "query_string": {
            "query":"(new york city) OR (big apple)",
            "default_field": ["subtitle"]
        }
    }
}'
  1. Term 查询
    全文查询在查询前会将查询内容分析为词项,然后进行查询; term 查询不对查询内容进行分析,是对值进行精确的查询。Term 查询不会计算查询结果的分数(score),属于过滤查询(filter context)。
    a. term 和 terms
    对指定的一个和多个内容进行精确查询
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
    "query": {
        "terms" : { "user" : ["kimchy", "elasticsearch"]}
    }
}
'

b. range 查询
文档属性值在一个范围的查询。可以是字符串、数字、日期。

curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
    "query": {
        "range" : {
            "age" : {
                "gte" : 10,
                "lte" : 20
            }
        }
    }
}'

c. exists 查询
查找指定属性至少又一个非空值的文档。

curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
    "query": {
        "exists" : { "field" : "user" }
    }
}'

d. wildcard 查询
根据通配符进行查询(? 匹配1个任意字符;* 匹配多个任意字符)。查询会耗性能。

curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
    "query": {
        "wildcard" : { "user" : "ki*y" }
    }
}'

复合查询

将多个简单查询通过组合起来就是一个复合查询了。常用的组合方式有下面几种。

  1. constant_score。这个查询里面的查询将不再计算分数,统一返回指定的分数。
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
    "query": {
        "constant_score" : {
            "filter" : {
                "term" : { "user" : "kimchy"}
            },
            "boost" : 2
        }
    }
}'

查询结果所有文档的 _score 都为 2 。

  1. bool
    逻辑组合,包括 must、should、must_not、filter。must 和 should 的查询会计算分数,其他的不会。
    must 必须包含; should 单独查询的时候,至少需要满足一个条件,与 must、filter 组合的时候可以不需要满足。
上一篇下一篇

猜你喜欢

热点阅读