美文网首页
Elasticsearch 入门

Elasticsearch 入门

作者: yangjingqzp | 来源:发表于2018-12-02 21:00 被阅读0次

    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 组合的时候可以不需要满足。

    相关文章

      网友评论

          本文标题:Elasticsearch 入门

          本文链接:https://www.haomeiwen.com/subject/fmsiqqtx.html