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

相关推荐
AI茶水间管理员14 小时前
如何让LLM稳定输出 JSON 格式结果?
前端·人工智能·后端
其实是白羊14 小时前
我用 Vibe Coding 搓了一个 IDEA 插件,复制URI 再也不用手动拼了
后端·intellij idea
用户83562907805114 小时前
Python 操作 Word 文档节与页面设置
后端·python
酒後少女的夢15 小时前
设计模式教程
后端·架构
凌览15 小时前
别再手搓 Skill 了,用这个工具 5 分钟搞定
前端·后端
weixin_4080996715 小时前
python请求文字识别ocr api
开发语言·人工智能·后端·python·ocr·api·ocr文字识别
weixin_4080996715 小时前
【组合实战】OCR + 图片去水印 API:自动清洗图片再识别文字(完整方案 + 代码示例)
图像处理·后端·ocr·api·文字识别·去水印·ocr识别优化
gelald15 小时前
SpringBoot - Actuator与监控
java·spring boot·后端
用户5853437884315 小时前
AI Harness Engineering:从概念、场景到落地方法
人工智能·后端