侧边栏壁纸
  • 累计撰写 98 篇文章
  • 累计创建 20 个标签
  • 累计收到 3 条评论

ElasticSearch学习笔记

林贤钦
2020-12-03 / 0 评论 / 0 点赞 / 546 阅读 / 6,901 字
温馨提示:
本文最后更新于 2021-03-03,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

ElasticSearch学习笔记

ElasticSearch官方文档

一、ElasticSearch简介

ElasticSearch,简称es,是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据;本身扩展性好,可以扩展上百台服务器,处理PB级别的数据。es也使用java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的Restful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。

ElasticSearch对比Solr

  • Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能;
  • Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式;
  • Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供;
  • Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于 Elasticsearch

二、基本概念

2.1 节点Node 与 集群Cluster

Elastic 本质上是一个分布式数据库,允许多台服务器协同工作,每台服务器可以运行多个 Elastic 实例。

单个 Elastic 实例称为一个节点(node)。一组节点构成一个集群(cluster)。

2.2 索引 Index

Elastic 会索引所有字段,经过处理后写入一个反向索引(Inverted Index)。查找数据的时候,直接查找该索引。Elastic 数据管理的顶层单位就叫做 Index(索引)。它是单个数据库的同义词。每个 Index (即数据库)的名字必须是小写。

2.3 文档 Document

  • Elasticsearch不会将信息存储为列数据的行,而是存储已序列化为JSON文档的复杂数据结构。当集群中有多个Elasticsearch节点时,存储的文档将分布在集群中,并且可以从任何节点立即访问。

  • Index 里面单条的记录称为 Document(文档)。许多条 Document 构成了一个 Index。同一个 Index 里面的 Document,不要求有相同的结构(scheme),但是最好保持相同,这样有利于提高搜索效率。

关于文档和索引

索引可以认为是文档的优化集合,每个文档都是字段的集合,这些字段是包含数据的键值对。默认情况下,Elasticsearch对每个字段中的所有数据建立索引,并且每个索引字段都具有专用的优化数据结构。例如,文本字段存储在倒排索引中,数字字段和地理字段存储在BKD树中。使用按字段数据结构组合并返回搜索结果的能力使Elasticsearch如此之快。

2.4 类型 type

在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型。

Elastic 6.x 版只允许每个 Index 包含一个 Type,7.x 版彻底移除 Type。

2.5 字段 Field

相当于是数据表的字段,对文档数据根据不同属性进行的分类标识

2.6 映射 mapping

mapping是处理数据的方式和规则方面做一些限制,如某个字段的数据类型、默认值、分析器、是否被索引等等,这些都是映射里面可以设置的,其它就是处理es里面数据的一些使用规则设置也叫做映射,按着最优规则处理数据对性能提高很大,因此才需要建立映射,并且需要思考如何建立映射才能对性能更好。

2.7 分片 shards

一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。为了解决这个问题,Elasticsearch提供了将索引划分成多份的能力,这些份就叫做分片。

分片有两种类型:主数据库和副本数据库。索引中的每个文档都属于一个主分片。副本分片是主分片的副本。副本可提供数据的冗余副本,以防止硬件故障并提高处理读取请求(如搜索或检索文档)的能力。

Elasticsearch索引实际上只是一个或多个物理碎片的逻辑分组,其中每个碎片实际上是一个独立的索引。通过在多个分片之间的索引中分配文档,并在多个节点之间分配这些分片,Elasticsearch可以确保冗余,这既可以防止硬件故障,又可以在将节点添加到集群中时提高查询能力

2.8复制 replicas

网络传输的情况下,故障可能会随时发生,有一个故障恢复机制是必须的,所以ES允许你制作一个或多个副本。每个索引可以被分成多个分片。一个索引也可以被复制0次(意思是没有复制)或多次。一旦复制了,每个索引就有了主分片(作为复制源的原来的分片)和复制分片(主分片的拷贝)之别。分片和复制的数量可以在索引创建的时候指定。

复制的两个主要原因

(1)高可用。它提供了高可用的机制以来防止分片或者节点宕机。为此,绝对不要将一个分片的副本放在跟这个分片相同的机器上。
(2)高并发。它允许你的分片可以提供超出自身吞吐量的搜索服务,搜索行为可以在分片所有的拷贝中并行执行。

三、ElasticSearch的客户端操作

3.1 Index操作

新建 Index,可以直接向 Elastic 服务器发出 PUT 请求。下面的例子是新建一个名叫accounts的 Index。

PUT localhost:9200/accounts

服务器返回一个 JSON 对象,里面的acknowledged字段表示操作成功。

{
    "acknowledged": true,
    "shards_acknowledged": true,
    "index": "accounts"
}

然后,我们发出 DELETE 请求,删除这个 Index。

DELETE localhost:9200/accounts

3.2 Mapping操作

注意:7.x之后是不需要加Type字段的,7.x会有一个默认的type:“_doc”,如果是7.0以下,需要mapping和properties中加Type字段

PUT localhost:9200/accounts

请求体:

{
  "mappings": {
      "properties": {
        "user": {
          "type": "text",
          "analyzer": "ik_max_word",
          "search_analyzer": "ik_max_word"
        },
        "title": {
          "type": "text",
          "analyzer": "ik_max_word",
          "search_analyzer": "ik_max_word"
        },
        "desc": {
          "type": "text",
          "analyzer": "ik_max_word",
          "search_analyzer": "ik_max_word"
        }
     }
   }
}

在这段代码中,会创建一个accounts的 Index,有三个字段

  • user
  • title
  • desc

analyzer是字段文本的分词器,search_analyzer是搜索词的分词器。ik_max_word分词器是插件ik提供的,可以对文本进行最大数量的分词

3.3 document操作

7.x之后是不需要加Type字段的,7.x会有一个默认的type:“_doc”,所以我们需要在index后面加 “_doc”

(1)创建文档document

PUT localhost:9200/accounts/_doc/1

请求体:

{
  "user": "张三",
  "title": "工程师",
  "desc": "数据库管理"
}

最后的1是该条记录的 Id。它不一定是数字,任意字符串(比如abc)都可以,甚至我们可以不加这个数字,但是es会给我们生成一个随机字符串

(2)修改文档document

POST localhost:9200/accounts/_doc/1

请求体:

{
  "user": "[修改]张三",
  "title": "[修改]工程师",
  "desc": "[修改]数据库管理"
}

(3)删除文档document

DELETE localhost:9200/accounts/_doc/1

(4)查询文档-id查询

GET localhost:9200/accounts/_doc/1

查询的结果,如果 Id 不正确,就查不到数据,found字段就是false

{
    "_index": "accounts",
    "_type": "_doc",
    "_id": "1",
    "_version": 3,
    "_seq_no": 5,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "user": "[修改]张三",
        "title": "[修改]工程师",
        "desc": "[修改]数据库管理"
    }
}

(5)查询文档-querystring查询

GET localhost:9200/accounts/_doc/_search

如果不加请求体,会查询该index下所有的文档数据

请求体:

{
    "query": {
        "query_string": {
            "default_field": "desc",
            "query": "系统"
        }
    }
}

查询结果:

{
    "took": 15,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 1,
            "relation": "eq"
        },
        "max_score": 1.0126972,
        "hits": [
            {
                "_index": "accounts",
                "_type": "_doc",
                "_id": "zy9CJ3YBnMXTjJIqhNLy",
                "_score": 1.0126972,
                "_source": {
                    "user": "李四",
                    "title": "工程师",
                    "desc": "系统管理"
                }
            }
        ]
    }
}

可以看到,通过desc字段查询系统,只有一条数据,实际上我加了两条数据,接下来我重新请求,返回的结果将不一样,只改query的字段

{
    "query": {
        "query_string": {
            "default_field": "desc",
            "query": "管理"
        }
    }
}

可以看到,多了一条数据

{
    "took": 18,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 2,
            "relation": "eq"
        },
        "max_score": 0.13786995,
        "hits": [
            {
                "_index": "accounts",
                "_type": "_doc",
                "_id": "zy9CJ3YBnMXTjJIqhNLy",
                "_score": 0.13786995,
                "_source": {
                    "user": "李四",
                    "title": "工程师",
                    "desc": "系统管理"
                }
            },
            {
                "_index": "accounts",
                "_type": "_doc",
                "_id": "1",
                "_score": 0.12562492,
                "_source": {
                    "user": "[修改]张三",
                    "title": "[修改]工程师",
                    "desc": "[修改]数据库管理"
                }
            }
        ]
    }
}

上面代码中,返回结果的 took字段表示该操作的耗时(单位为毫秒),timed_out字段表示是否超时,hits字段表示命中的记录,里面子字段的含义如下。

  • total:返回记录数,本例是2条。
  • max_score:最高的匹配程度,本例是1.0
  • hits:返回的记录组成的数组。

3.4 IK分词器分词操作

es默认会将查询的每个字段进行分词,根据每个关键词进行搜索,所以我们使用IK分词器,比如我是程序员,ik分词器的ik_smart将切分为:我,是,程序员,ik分词器的ik_max_word将切分为:我,是,程序员,程序,员,但是如果是标准的es分词器,将会分词成:我,是,程,序,员。

0

评论区