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 就开一篇小说😄。

相关推荐
2401_857622662 小时前
SpringBoot框架下校园资料库的构建与优化
spring boot·后端·php
2402_857589362 小时前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
hengzhepa3 小时前
ElasticSearch备考 -- Async search
大数据·学习·elasticsearch·搜索引擎·es
哎呦没3 小时前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
_.Switch4 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
杨哥带你写代码5 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
AskHarries6 小时前
读《show your work》的一点感悟
后端
A尘埃6 小时前
SpringBoot的数据访问
java·spring boot·后端
yang-23076 小时前
端口冲突的解决方案以及SpringBoot自动检测可用端口demo
java·spring boot·后端
Marst Code6 小时前
(Django)初步使用
后端·python·django