ES笔记:基础概念和使用

ES全称ElasticSearch,是一个开源的高扩展的实时的分布式全文检索和分析引擎,主要用于全文检索、结构化搜索、分析,扩展性非常好,可以扩展到上百台服务器,处理PB级别(1PB=1024TB)的数据。使用的编程语言为Java,以Lucene为核心,以RESTful API风格来实现索引和搜索的功能,让全文搜索变得更加简单。

注: 此笔记使用的ES版本为7.6.1

API文档: API conventions | Elasticsearch Guide [8.5] | Elastic

1 下载安装

1.1 ES下载安装

下载地址: https://www.elastic.co/cn/downloads/past-releases#elasticsearch

Windows安装: windows版本下载下来后解压即可使用。配置文件在 config/elasticsearch.yml ,默认端口为9200,ES启动路径为 bin/elasticsearch.bat (直接在dos窗口运行该文件即可(或直接鼠标双击也行)),启动后浏览器访问 http://localhost:9200/ ,出现经典的“You Know, for Search”则表示启动成功。

1.2 Kibana下载安装

Kibana是一个专门用于ElasticSearch的开源分析和可视化平台,可以用来搜索和查看ES中的数据,使用的时候注意需要 下载与ES一致的版本

下载地址: https://www.elastic.co/cn/downloads/kibana

Windows安装: Kibana也是解压即用的包,不过运行之前需要把依赖包装一下。在dos窗口cd到解压目录,执行 cnpm intall 安装依赖包即可(cnpm可以直接百度怎么安装和配置),然后直接运行 bin/kibana.bat 就可以了。注意运行Kibana的时候需要保证ES已经启动运行好了,否则Kibana无法顺利启动。最后按照提示访问默认的端口即可 http://localhost:5601/

Kibana中文配置: Kibana默认的语言是英文,可以通过修改配置将其设置为中文,支持的中文配置文件在安装目录下的 x-pack\plugins\translations\translations\zh-CN.json ,配置时在安装目录的 config/kibana.yml 文件中修改 i18n.locale: "en"i18n.locale: "zh-CN" (英文的配置默认是注释掉的,所以只需要将中文的配置直接添加进去即可),配置修改后,重启Kibana即可。

2 基础概念

2.1 集群

ES是按照集群进行设计的,即便我们只安装了一个节点(服务器),也是按集群来运行的,这个默认的集群名称就是elasticsearch。

2.2 索引和文档

索引(index)是面向文档(document)的,一个索引中可以有多个文档,文档是ES中“一条数据”的最小表示单位。与关系数据库作类比,一个文档相当于关系数据库中的一条数据(记录)或一个实例对象,关系数据库中表的字段或对象的属性在ES中使用field来描述,而一个field则使用key-value键值对来存储。

ES中最大的特色就是一切皆json,由此一个文档中可以非常方便的增加或删除一个字段(field),而不用担心破坏或影响这条数据(文档)。

2.3 分片

ES后台会默认将索引进行分片,并将这些“片”分散存储在集群中不同的节点上。

2.5 分词

将一段中文、英文或别的语言划分成一个一个的关键字,如“倒排索引”可以分为“倒排”、“索引”、“倒”、“排”等词,中文默认按字进行拆分,英文则默认按单词拆分。我们在使用百度、Google等搜索引擎进行搜索的时候,就是先将输入的内容进行分词(关键字),再按分词结果去数据库中进行搜索。

2.5 倒排索引

ES特色之一就是使用了倒排索引来更好地支持全文搜索。倒排索引的基础原理就是将文档进行分词(分词是指将文档按词拆分,如“倒排索引”可以分为“倒排”、“索引”、“倒”、“排”等词,英文则通常按单词划分),然后记录分词对应的文档,当用户搜索某个关键词时,ES会使用分词为每个文档“计分”(score),文档中该关键词出现的越多,得分就会越高,反之则越低,而文档分数越高,则它出现在搜索结果中的权重就会越大。

3 基础使用

ES中对于数据操作,包括创建索引、文档,查询文档数据等都是通过REST请求的方式,具体的ES使用方式和语法会在请求的URL和请求体中体现。

3.1 基础REST操作

Method URL 说明
PUT /索引名 创建索引
POST /索引名/_doc/文档id 创建指定id的文档
POST /索引名/_create/文档id 创建指定id的文档
POST /索引名/_doc 创建随机id的文档
POST /索引名/_update/文档id 更新指定id的文档
DELETE /索引名/_doc/文档id 删除指定文档
GET /索引名/_doc/文档id 查询指定文档
POST /索引名/_doc/_search 查询该索引的所有文档

3.2 基本数据类型

字符串: text(可以进行分词)、keyword(作为一个整体“单词”,不可被继续分词)。
数值: long、integer、short、byte、double、float、half_float、scaled_float。
日期: date。
布尔值: boolean。
二进制: binary。

示例: 创建一个索引并为每个字段指定数据类型,此时并未创建任何文档数据。(以下示例中可以使用 PUT /index2/_mapping 对已创建的映射关系进行修改,此时请求体第一层的key就直接是properties了)

# 请求url:PUT /index2
{
    "mappings": {
        "properties": {
            "name": {
                "type": "text"
            },
            "age": {
                "type": "long"
            },
            "birthday": {
                "type": "date"
            }
        }
    }
}

3.3 常用内置REST操作

查看ES健康状况

GET _cat/health

查询结果如 1683566272 17:17:52 elasticsearch yellow 1 1 5 5 0 0 2 0 - 71.4%

查看所有索引基本情况

GET _cat/indices

查询结果如 yellow open index1 fqDrMEiuSW6SKsBXgzXf8Q 1 1 1 0 3.7kb 3.7kb

查看ES集群节点信息

GET _cat/nodes

查看ES集群信息

GET /_cluster/health

3.4 简单查询

如果只是简单的查询,可以在url中直接使用查询参数q指定查询条件。

示例: GET /index1/_search?q=name:zhangsan

查询url中不用带上type类型值,使用_search表示搜索,q表示url中的查询参数key,name指要查询的字段名称,冒号后面就是要匹配的值(如果字段类型是keyword,那么就只能整词匹配,相当于精确匹配)。查询结果如下(查询结果中的score表示结果的匹配度,匹配度越高,则score的值越高):

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.2876821,
    "hits" : [
      {
        "_index" : "index1",
        "_type" : "type1",
        "_id" : "1",
        "_score" : 0.2876821,
        "_source" : {
          "name" : "zhangsan",
          "age" : 18
        }
      }
    ]
  }
}

3.5 复杂查询

3.5.1 query查询

复杂的查询可以在请求体中使用query参数指定条件。如:

GET /index1/_search
{
  "query": {
    "match": {
      "name": "zhangsan"
    }
  }
}

同一个字段如果想要多条件查询,达到类似 name in ('zhangsan, 'lisi') 的效果,则可以使用空格将条件分开,如 "name": "zhangsan lisi"

常用匹配条件:

  • match:分词匹配,需要指定匹配的字段及其值,需要注意的是此处“词”的概念,是指分词器分完词之后的词。
  • match_phrase:全词(精确)匹配,会将key-value中的value作为一个整体去进行匹配。
  • match_all:查询全量数据,对应json体可以不用传值,使用一个空的{}即可。

查询结果示例及其字段解释:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {  # hits即查询结果,这个json中保存的是结果相关的数据
    "total" : {  # 查询到的总量描述
      "value" : 1,  # 查询结果条数
      "relation" : "eq"  # 查询的方式
    },
    "max_score" : 0.9808291,  # 查询结果中最大的score
    "hits" : [  # 查询到的结果列表,即文档列表,一个json表示一个文档
      {
        "_index" : "index1",
        "_type" : "type1",
        "_id" : "1",
        "_score" : 0.9808291,  # 此条数据的匹配score值
        "_source" : {  # 文档中其他自定义的属性值
          "name" : "zhangsan",
          "age" : 18
        }
      }
    ]
  }
}

3.5.2 _source过滤

_source参数用于对查询结果过滤,指定查询结果需要返回的字段,不指定则默认返回文档中的全部字段。

GET /index1/_search
{
  "query": {
    "match": {
      "name": "zhangsan"
    }
  },
  "_source": ["name"]  # 指定返回结果的_source字段
}

3.5.3 sort排序

使用sort参数可以对查询结果进行排序。

GET /index1/_search
{
  "sort": {
    "age": {  # 根据age字段进行升序排序
      "order": "asc"
    }
  }
}

3.5.4 from/size分页查询

from/size参数用于指定对结果进行分页,表示起始编号(从0开始)和每页的数据条数。

GET /index1/_search
{
  "sort": {
    "age": {
      "order": "asc"
    }
  },
  "from": 0,
  "size": 1
}

3.5.5 must/should/must_not查询

在ES中想要达到SQL中and/or/not的效果,可以使用bool参数,在其json中进一步指定must参数(相当于and)、should参数(相当于or)、must_not参数(相当于not)。

GET /index1/_search
{
  "query": {
    "bool": {  # 同时指定name和age作为查询条件
      "must": [  # must表示列表中的查询条件都需要满足
        {
          "match": {
            "name": "zhangsan"
          }
        },
        {
          "match": {
            "age": 18
          }
        }
      ]
    }
  }
}

3.5.6 filter过滤器

filter过滤器也是在bool参数中使用,range表示范围过滤, gte表示大于等于(大于则是 gt), lte表示小于等于(小于则是le)。

GET /index1/_search
{
  "query": {
    "bool": {
      "filter": {
        "range": {
          "age": {
            "gte": 10,
            "lte": 20
          }
        }
      }
    }
  }
}

3.5.7 term精确匹配

term参数精确匹配,会根据类型为keyword的字段进行全词匹配,当字段类型为text时,还是会使用分词器进行模糊匹配。该参数与match参数不同的是,使用空格时会将空格视为一个整体的查询条件,不会进行多条件查询。

GET /index1/_search
{
  "query": {
    "term": {
      "name": "zhangsan"
    }
  }
}

3.5.8 highlight高亮

该参数在会查询结果中将匹配成功的词添加 <em></em> 标签,如果想要自定义高亮标签,可以使用 pre_tagspost_tags 指定。

GET /index1/_search
{
  "query": {
    "term": {
      "name": "zhangsan"
    }
  },
  "highlight": {
    "fields": {
      "name": {}
    }
  }
}

查询结果示例:

{
  "took" : 196,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.9808291,
    "hits" : [
      {
        "_index" : "index1",
        "_type" : "type1",
        "_id" : "1",
        "_score" : 0.9808291,
        "_source" : {
          "name" : "zhangsan",
          "age" : 18
        },
        "highlight" : {
          "name" : [
            "<em>zhangsan</em>"
          ]
        }
      }
    ]
  }
}

自定义高亮标签及其查询结果示例:

GET /index1/_search
{
  "query": {
    "term": {
      "name": "zhangsan"
    }
  },
  "highlight": {
    "pre_tags": "<p class='key' style='color:red'>",
    "post_tags": "</p>", 
    "fields": {
      "name": {}
    }
  }
}
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.9808291,
    "hits" : [
      {
        "_index" : "index1",
        "_type" : "type1",
        "_id" : "1",
        "_score" : 0.9808291,
        "_source" : {
          "name" : "zhangsan",
          "age" : 18
        },
        "highlight" : {
          "name" : [
            "<p class='key' style='color:red'>zhangsan</p>"
          ]
        }
      }
    ]
  }
}

3.5.9 aggs聚合查询

可以使用aggs进行计数、平均值计算等聚合查询,由于查询时会将原始数据一并返回,当你不想要原始数据时,可以使用 "size": 0 参数(和aggs参数同级)过滤掉原始数据。

GET /index1/_search

{
    "aggs": {  # 聚合查询
        "age_group": {    # 查询结果命名,可以自定义
            "terms": {  # 聚合方式:terms表示按项进行统计(个数),相当于SQL中的group by。
                "field": "age"    # 需要聚合的字段
            }
        }
    }
}

查询结果:

{
    "took": 31,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 3,
            "relation": "eq"
        },
        "max_score": 1.0,
        "hits": [
            {
                "_index": "index1",
                "_type": "type1",
                "_id": "2",
                "_score": 1.0,
                "_source": {
                    "name": "lisi",
                    "age": 19
                }
            },
            {
                "_index": "index1",
                "_type": "type1",
                "_id": "3",
                "_score": 1.0,
                "_source": {
                    "name": "wangwu",
                    "age": 20
                }
            },
            {
                "_index": "index1",
                "_type": "type1",
                "_id": "1",
                "_score": 1.0,
                "_source": {
                    "age": 17,
                    "name": "zhangsan"
                }
            }
        ]
    },
    "aggregations": {
        "age_group": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
                {
                    "key": 17,
                    "doc_count": 1
                },
                {
                    "key": 19,
                    "doc_count": 1
                },
                {
                    "key": 20,
                    "doc_count": 1
                }
            ]
        }
    }
}
posted @ 2024-02-04 01:15  山上下了雪-bky  阅读(47)  评论(0编辑  收藏  举报