ElasticSearch 介绍与基本使用

本篇文档首先向大家简单介绍下 ES,然后介绍它的存储形式,以及如何使用查询。对比相当于 MySQL 数据库的表结构和 SQL 语句。本篇文章并不涉及底层原理,仅仅介绍如何使用。

ElasticSearch 介绍

ES 官方文档

ES 是基于 Java 语言进行开发,它的内部使用 Lucene 做索引与搜索,但是它的目的是使全文检索变得简单,通过隐藏 Lucene 的复杂性,取而代之的提供一套简单一致的 RESTful API。

Elasticsearch 不仅仅是 Lucene,并且也不仅仅只是一个全文搜索引擎。 它可以被下面这样准确的形容:

  • 一个分布式的实时文档存储,每个字段 可以被索引与搜索
  • 一个分布式实时分析搜索引擎
  • 能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据

数据存储

基本概念介绍

document

文档可以对应为数据库中的一行数据,ES 使用 JSON 作为文档的序列化格式,大多数的编程语言都支持序列化,下面这个 JSON 文档代表一个 user 对象。

js 复制代码
{
    "email":      "john@smith.com",
    "first_name": "John",
    "last_name":  "Smith",
    "info": {
        "bio":         "Eco-warrior and defender of the weak",
        "age":         25,
        "interests": [ "dolphins", "whales" ]
    },
    "join_date": "2014/05/01"
}

index

如何将上面的用户对象存储到 ES 集群中,首先要确定存储的位置,存储的位置就是索引,索引就相当于数据库。

一个Elasticsearch集群可以包含多个索引 ,相应的每个索引可以包含多个类型 。这些不同的类型存储着多个文档 ,每个文档还有多个属性

basic 复制代码
curl -XPUT 'localhost:9200/customer/external/1?pretty&pretty' -d'
{
  "name": "John Doe"
}'
  • customer: 索引名称
  • external: 类型名称
  • 1: 特定的客户 ID

请求之后的响应结构如下所示:

js 复制代码
{  
    "_index":"customer",  
    "_type":"external",  
    "_id":"1",  
    "_version":1,  
    "result":"created",  
    "_shards":**{  
        "total":2,  
        "successful":1,  
        "failed":0  
    },  
    "created":true  
}

字段类型

ES 中可以指定字段为两种类型,分别为 keyword 和 text。keyword 不支持分词,进行完全匹配。text 字段进行分词,适用于后续的全文索引。

指定字段类型时分为三步,分别是创建索引、定义字段类型和添加数据。其中通过索引映射(Index Mapping)来定义字段类型。如下所示,指定 title 字段为 text 类型。

js 复制代码
PUT /my-index 

{  
    "mappings":{  
        "properties":{  
            "title":{  
                "type":"text"  
            }  
        }  
    }  
}

数据查询

基本查询

上文中,我们将数据存储到 ES 中,下面我们演示下如何搜索到存储的数据

basic 复制代码
curl -XGET 'localhost:9200/customer/external/1?pretty&pretty'

{
  "name": "John Doe"
}'

点击查看返回数据

json 复制代码
{
  "_index" : "customer",
  "_type" : "external",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "_source" : { "name": "John Doe" }
}

在返回的 source 字段中,包含了全部的 customer 索引下的文档。除了上面的基本查询,返回全部的数据之外,我们再看下其他的查询请求,请求参数分别在浏览器 url 中和 body 中,其返回的数据不变

basic 复制代码
// 请求参数在 url 中
curl -XGET 'localhost:9200/bank/_search?q=*&sort=account_number:asc&pretty'

// 请求参数在 body 中
curl -XGET 'localhost:9200/bank/_search?pretty' -d'
{
  "query": { "match_all": {} },
  "sort": [
    { "account_number": "asc" }
  ]
}'
  • bank: 是指查询的索引
  • q=* : 返回索引中所有的文档
  • pretty: 告诉 ES 返回漂亮的 JSON 数据

点击查看返回数据

ruby 复制代码
{  
    "took":63,  
    "timed_out":false,  
    "_shards":**{  
        "total":5,  
        "successful":5,  
        "failed":0  
    },  
    "hits":**{  
        "total":1000,  
        "max_score":null,  
        "hits":**[  
            **{  
                "_index":"bank",  
                "_type":"account",  
                "_id":"0",  
                "sort":**[  
                    0  
                ],  
                "_score":null,  
                "_source":**{  
                    "account_number":0,  
                    "balance":16623,  
                    "firstname":"Bradshaw",  
                    "lastname":"Mckenzie",  
                    "age":29,  
                    "gender":"F",  
                    "address":"244 Columbus Place",  
                    "employer":"Euron",  
                    "email":"bradshawmckenzie@euron.com",  
                    "city":"Hobucken",  
                    "state":"CO"  
                }  
            },  
            **{  
                "_index":"bank",  
                "_type":"account",  
                "_id":"1",  
                "sort":**[  
                    1  
                ],  
                "_score":null,  
                "_source":**{  
                    "account_number":1,  
                    "balance":39225,  
                    "firstname":"Amber",  
                    "lastname":"Duke",  
                    "age":32,  
                    "gender":"M",  
                    "address":"880 Holmes Lane",  
                    "employer":"Pyrami",  
                    "email":"amberduke@pyrami.com",  
                    "city":"Brogan",  
                    "state":"IL"  
                }
            },
            ...
        ]  
    }  
}

返回的数据部分参数释义如下所示:

  • took - Elasticsearch 执行搜索的时间(毫秒)
  • time_out - 告诉我们搜索是否超时
  • _shards - 告诉我们多少个分片被搜索了,以及统计了成功/失败的搜索分片
  • hits - 搜索结果
  • hits.total - 搜索结果
  • hits.hits - 实际的搜索结果数组(默认为前 10 的文档)
  • sort - 结果的排序 key (键)(没有则按 score 排序)
  • scoremax_score -现在暂时忽略这些字段

Query DSL

Elasticsearch 提供了一个可以执行查询的 Json 风格的 DSLdomain-specific language 领域特定语言)。这个被称为 Query DSL。如下所示,将介绍基本的查询参数。

basic 复制代码
curl -XGET 'localhost:9200/bank/_search?pretty' -d'
{
  "query": { "match": { "account_number": 20 } },
  "from": 10,
  "size": 10,
  "sort": { "balance": { "order": "desc" } },
  "_source": ["account_number", "balance"]
}'
  • query: query 参数传递的参数为 match_all 代表的是返回索引下全部的文档, account_number:20 代表返回账号为 20 的文档。
  • from: 返回这个索引的第 11 条数据到第 20 条数据。
  • size: 返回数据大小,默认为 10 条数据
  • sort: 对账户余额做降序排序
  • source: 返回数据只包含 account_number 和 balance 两个字段

在 match 中,我们可以指定字段必须满足两个条件 / 满足其中一个条件 / 即满足一个条件但并不满足另外一个条件,查询如下所示:

css 复制代码
// address 中包含 mill 或者 lane 
curl -XGET 'localhost:9200/bank/_search?pretty' -d'
{
  "query": { "match": { "address": "mill lane" } }
}'

// address 中包含 mill 和 lane 
curl -XGET 'localhost:9200/bank/_search?pretty' -d'
{
  "query": {
    "bool": {
      "must": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}'

// address 中包含 mill 或者 lane 
curl -XGET 'localhost:9200/bank/_search?pretty' -d'
{
  "query": {
    "bool": {
      "should": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}'

// 找出账户余额 20000 至 30000 的数据

curl -XGET 'localhost:9200/bank/_search?pretty' -d'
{
  "query": {
    "bool": {
      "must": { "match_all": {} },
      "filter": {
        "range": {
          "balance": {
            "gte": 20000,
            "lte": 30000
          }
        }
      }
    }
  }
}'

// 执行聚合,以下相当于 
curl -XGET 'localhost:9200/bank/_search?pretty' -d'
{
  "size": 0,
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state.keyword"
      }
    }
  }
}'

相当于 SQL:
SELECT state, COUNT(*) FROM bank GROUP BY state ORDER BY COUNT(*) DESC
  • bool must 语句指定了所有查询必须为 true 时将匹配到文档
  • bool should 语句指定了一个查询列表,两者中的一个为 true 时将匹配到文档
  • bool must_not 语句指定了一个查询列表,都不为 true 将匹配到文档

客户端类库推荐

使用Java High Level REST Client操作elasticsearch

目前本人就职于知乎,后续想写一篇本人的职场经历(从 17 年至今)。点赞超过 20 就开一篇小说😄。

相关推荐
序安InToo27 分钟前
第6课|注释与代码风格
后端·操作系统·嵌入式
xyy12328 分钟前
C#: Newtonsoft.Json 到 System.Text.Json 迁移避坑指南
后端
洋洋技术笔记30 分钟前
Spring Boot Web MVC配置详解
spring boot·后端
JxWang0531 分钟前
VS Code 配置 Markdown 环境
后端
navms34 分钟前
搞懂线程池,先把 Worker 机制啃明白
后端
JxWang0534 分钟前
离线数仓的优化及重构
后端
Nyarlathotep011335 分钟前
gin01:初探gin的启动
后端·go
JxWang0535 分钟前
安卓手机配置通用多屏协同及自动化脚本
后端
JxWang0537 分钟前
Windows Terminal 配置 oh-my-posh
后端
SimonKing1 小时前
OpenCode AI编程助手如何添加Skills,优化项目!
java·后端·程序员