elasticsearch的安装与基础入门

使用docker启动单节点集群

docker pull docker.elastic.co/elasticsearch/elasticsearch:8.1.2
docker network create elastic
docker run --name es01 --net elastic -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -it docker.elastic.co/elasticsearch/elasticsearch:8.1.2

默认使用ssl,修改配置文件禁用ssl,启动容器服务,进入目录:/usr/share/elasticsearch/config
修改配置文件elasticsearch.yml,修改下面一行true-->false,重启服务
xpack.security.enabled: false

参考文档

配置中文分词器ik

  1. 下载Ik分词器,下载链接见官网
    官网 IK8.1.2下载链接

  2. 将下载文件解压
    unzip elasticsearch-analysis-ik-8.1.2.zip

  3. 在 es/plugins 目录下,新建 ik 目录,并将解压后的所有文件拷贝到 ik 目录下。

  4. 重启es服务

基本概念

  1. index
    查看当前节点的所有Index
    curl http://ip:9200/_cat/indices?v ?v的意思是打印标题

  2. document
    index里面的单条记录称为document,许多document构成了一个index,document使用Json格式表示,
    同一个Index里面的document不要求有相同的结构(schema),但是最好相同,这样有利于提高搜索效率

  3. type
    document可以分组,比如weather这index里面,可以按城市分组,也可以按气候分组,不同type应该有相同的结构(schema)
    比如说Id字段不能在这个组是字符串,在另外一个组是是数值
    列出每个index下所包含的type
    curl http://ip:9200/_mapping?pretty=true

  • 根据规划,Elastic 6.x 版只允许每个 Index 包含一个 Type,7.x 版将会彻底移除 Type。

新建和删除index

  1. 新建index
    curl -X PUT ip:9200/weather

  2. 删除index
    delete http://ip:9200/weather

数据操作

  1. 向指定Index添加一条记录
    put/post http://ip:9200/accounts/_doc/1
    body:
{
  "user": "张三",
  "title": "工程师",
  "desc": "数据库管理"
}
  • 注意:如果没有先创建Index(这个例子是accounts),直接执行上面的命令,es也不会报错,而是直接生成指定的Index
  1. 查看一条记录
    get http://ip:9200/accounts/_doc/1
{
    "_index": "accounts",
    "_id": "1",
    "_version": 2,
    "_seq_no": 1,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "user": "张三",
        "title": "工程师",
        "desc": "数据库管理"
    }
}

返回的数据中,found字段表示查找成功,_course字段返回原始记录
如果id不正确,就是查找不到数据found返回false

  1. 删除记录
    delete http://ip:9200/accounts/_doc/1
    删除成功result返回:deleted, 删除失败result返回:not_found

  2. 更新记录
    put http://ip:9200/accounts/_doc/1
    更新记录就是使用put请求重新发送一次数据,可以看到记录id没变,版本_version发生了变化
    result返回的是updated

数据查询

  1. 返回所有记录
    get http://mayanan.cn:9200/accounts/_search
    返回accounts索引下的所有记录
点击查看代码
{
    "took": 1,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 1,
            "relation": "eq"
        },
        "max_score": 1.0,
        "hits": [
            {
                "_index": "accounts",
                "_id": "1",
                "_score": 1.0,
                "_source": {
                    "user": "张三",
                    "title": "工程师",
                    "desc": "数据库管理,软件开发"
                }
            }
        ]
    }
}

took字段表示该操作的耗时,单位毫秒,time_out字段表示是否超时,hits字段表示命中的记录,hits里面字段的含义如下

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

返回的记录中,每条记录都有一个_score字段,表示匹配程度,默认是按照这个字段降序排列

  1. 全文搜索
    es的查询非常特别,使用自己的查询语法
    要求get请求带有数据体
{
    "query": {"match": {"desc": "管理"}}
}

上面的代码是使用match查询,指定的匹配条件是desc字段里面的“软件”这个词

  • es默认返回10条结果,可以通过size设置返回的结果数量
{
    "query": {"match": {"desc": "管理"}},
    "size": 1
}

上面代码,每次只返回一条结果
可以通过from字段,指定位移

{
    "query": {"match": {"desc": "管理"}},
    "size": 1,
    "from": 1
}

上面代码,从位置1开始(默认是从位置0开始),只返回一条结果

  1. 逻辑运算
    如果有多个搜索关键字,es认为它们是or关系
{
    "query": {"match": {"desc": "软件 系统"}}
}

上面代码搜索的是软件or系统
如果要执行多个关键词的and搜索,必须使用布尔查询

{
    "query": {
        "bool": {
            "must": [
                {"match": {"desc": "软件"}},
                {"match": {"desc": "系统"}}
            ]
        }
    }
}
  1. 查询一共有多少个文档
    查询索引下有多少个文档
    get http://ip:9200/accounts/_count
    查询集群下有多少个文档
    get http://ip:9200/_count
    请求参数
{
    "query": {
        "match_all": {}
    }
}
  • 在es中,将对象转化为json构建索引要比要比一个扁平的表结构中构建容易的多
  1. 全字段搜索
{
    "query":{
        "multi_match":{
            "query": "工程师"
        }
    }
}
  1. 还可以指定字段搜索
{
    "query":{
        "multi_match":{
            "query": "工程师",
            "fields": ["user", "desc", "title"]
        }
    }
}

  • http://ip:9200/megacorp/_doc/1
    get获取文档、put更新/添加文档、post添加/更新文档、delete删除文档
    先构建数据,索引员工文档
    post /megacorp/_doc/1
    post /megacorp/_doc/2
    post /megacorp/_doc/3
{
    "first_name" : "John",
    "last_name" :  "Smith",
    "age" :        25,
    "about" :      "I love to go rock climbing",
    "interests": [ "sports", "music" ]
}

{
    "first_name" :  "Jane",
    "last_name" :   "Smith",
    "age" :         32,
    "about" :       "I like to collect rock albums",
    "interests":  [ "music" ]
}

{
    "first_name" :  "Douglas",
    "last_name" :   "Fir",
    "age" :         35,
    "about":        "I like to build cabinets",
    "interests":  [ "forestry" ]
}
  1. 搜索指定索引下的所有文档
    get /megacorp/_search

  2. 通过查询字符串搜索文档
    get /megacorp/_search?q=last_name:Smith

  3. 使用DSL查询
    get /megacorp/_search

{
    "query":{
        "match":{
            "last_name":"smith"
        }
    }
}
  1. 按照所有字段检索
    get /megacorp/_search
{
    "query":{
        "multi_match":{
            "query": "Smith"
        }
    }
}
  1. 同样搜索姓氏为 Smith 的员工,但这次我们只需要年龄大于 30 的。
    使用filter过滤器,它支持高效的执行一个结构化查询
{
    "query": {
        "bool": {
            "must": {
                "match": {"last_name": "SMITH"}
            },
            "filter": {
                "range": {
                    "age": {"gt": 30}
                }
            }
        }
    }
}
  1. 全文搜索
    尝试一下高级点的全文搜索,一项传统数据库很难搞定的任务
{
    "query": {
        "match": {
            "about": "rock limbing"
        }
    }
}

es按照相关性得分排序,即每个文档跟查询的匹配程度,该案例说明了es如何在全文属性上搜索
并返回相关性最强的结果,es中相关性概念非常重要,也是完全区别于传统数据库的一个概念
数据库中的一条记录要么匹配,要么不匹配

  1. 短语搜索
    找出一个属性中的独立单词是没有问题的,但有时候想要精确匹配一系列单词或者_短语_ 。 比如, 我们想执行这样一个查询,仅匹配同时包含 “rock” 和 “climbing” ,并且 二者以短语 “rock climbing” 的形式紧挨着的雇员记录。
    get /megacorp/_search
{
    "query": {
        "match_phrase": {
            "about": "rock climbing"
        }
    }
}
  1. 高亮搜索
    get /megacorp/_search
{
    "query": {
        "match_phrase": {
            "about": "rock climbing"
        }
    },
    "highlight": {
        "fields": {
            "about": {}
        }
    }
}
  1. 分析
    es有一个功能叫做聚合,聚合与sql中的group by很相似,但功能更强大
    get /megacorp/_search
{
  "aggs": {
    "all_interests": {
      "terms": { "field": "interests.keyword" }
    }
  }
}

可以看到,两位员工对音乐感兴趣,一位对林业感兴趣,一位对运动感兴趣。这些聚合的结果数据并非预先统计,而是根据匹配当前查询的文档即时生成的。
如果想知道Smith员工最受欢迎的兴趣爱好,直接构造一个组合查询
get /megacorp/_search

{
    "query": {
        "match": {
            "last_name": "Smith"
        }
    },
    "aggs": {
        "all_interests": {
            "terms": { "field": "interests.keyword" }
        }
    }
}

聚合还支持分级汇总,比如查询特定兴趣爱好员工的平均年龄
get /megacorp/_search

{
    "aggs": {
        "all_interests": {
            "terms": { "field": "interests.keyword" },
            "aggs": {
                "avg_age": {
                    "avg": {"field": "age"}
                }
            }
        }
    }
}

输出是第一次聚合的加强版,依然有一个兴趣及数量的列表,只不过每个兴趣都有了一个附件加avg_age属性,
代表有这个兴趣爱好的所有员工的平均年龄,

  1. 教程结语
    欣喜的是,这是一个关于 Elasticsearch 基础描述的教程,且仅仅是浅尝辄止,更多诸如 suggestions、geolocation、percolation、fuzzy 与 partial matching 等特性均被省略,以便保持教程的简洁。但它确实突显了开始构建高级搜索功能多么容易。不需要配置——只需要添加数据并开始搜索!

  2. 分布式特性
    在本章开头,我们提到过 Elasticsearch 可以横向扩展至数百(甚至数千)的服务器节点,同时可以处理PB级数据。我们的教程给出了一些使用 Elasticsearch 的示例,但并不涉及任何内部机制。Elasticsearch 天生就是分布式的,并且在设计时屏蔽了分布式的复杂性。

Elasticsearch 在分布式方面几乎是透明的。教程中并不要求了解分布式系统、分片、集群发现或其他的各种分布式概念。可以使用笔记本上的单节点轻松地运行教程里的程序,但如果你想要在 100 个节点的集群上运行程序,一切依然顺畅。

Elasticsearch 尽可能地屏蔽了分布式系统的复杂性。这里列举了一些在后台自动执行的操作:

分配文档到不同的容器 或 分片 中,文档可以储存在一个或多个节点中
按集群节点来均衡分配这些分片,从而对索引和搜索过程进行负载均衡
复制每个分片以支持数据冗余,从而防止硬件故障导致的数据丢失
将集群中任一节点的请求路由到存有相关数据的节点
集群扩容时无缝整合新节点,重新分配分片以便从离群节点恢复
当阅读本书时,将会遇到有关 Elasticsearch 分布式特性的补充章节。这些章节将介绍有关集群扩容、故障转移(集群内的原理) 、应对文档存储(分布式文档存储) 、执行分布式搜索(执行分布式检索) ,以及分区(shard)及其工作原理(分片内部原理) 。

  1. 后续步骤
    现在大家对于通过 Elasticsearch 能够实现什么样的功能、以及上手的难易程度应该已经有了初步概念。Elasticsearch 力图通过最少的知识和配置做到开箱即用。学习 Elasticsearch 的最好方式是投入实践:尽情开始索引和搜索吧!

然而,对于 Elasticsearch 知道得越多,就越有生产效率。告诉 Elasticsearch 越多的领域知识,就越容易进行结果调优。

本书的后续内容将帮助你从新手成长为专家,每个章节不仅阐述必要的基础知识,而且包含专家建议。如果刚刚上手,这些建议可能无法立竿见影;但 Elasticsearch 有着合理的默认设置,在无需干预的情况下通常都能工作得很好。当你开始追求毫秒级的性能提升时,随时可以重温这些章节。

参考文档
参考文档

posted @ 2022-04-11 15:08  专职  阅读(103)  评论(0编辑  收藏  举报