es的返回数据结构

本文介绍了Elasticsearch(ES)的基本使用,包括样例数据导入、搜索API(请求参数方式与请求体方式)、查询语言DSL的简单示例、过滤查询以及聚合操作。通过这些内容,读者可以理解ES的返回数据结构,并学会如何执行常见的搜索和过滤操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ES即简单又复杂,你可以快速的实现全文检索,又需要了解复杂的REST API。本篇就通过一些简单的搜索命令,帮助你理解ES的相关应用。虽然不能让你理解ES的原理设计,但是可以帮助你理解ES,探寻更多的特性。

其他相关的内容参考:Elasticsearch官方文档翻译

样例数据

为了更好的使用和理解ES,没有点样例数据还是不好模拟的。这里提供了一份官网上的数据,accounts.json。如果需要的话,也可以去这个网址玩玩,它可以帮助你自定义写随机的JSON数据

首先开启你的ES,然后执行下面的命令,windows下需要自己安装curl、也可以使用cygwin模拟curl命令:

curl -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary  @accounts.json

注意:

1 需要在accounts.json所在的目录运行curl命令。

2 localhost:9200是ES得访问地址和端口

3 bank是索引的名称

4 account是类型的名称

5 索引和类型的名称在文件中如果有定义,可以省略;如果没有则必须要指定

6 _bulk是rest得命令,可以批量执行多个操作(操作是在json文件中定义的,原理可以参考之前的翻译)

7 pretty是将返回的信息以可读的JSON形式返回。

执行完上述的命令后,可以通过下面的命令查询:

curl 'localhost:9200/_cat/indices?v'
health index pri rep docs.count docs.deleted store.size pri.store.size
yellow bank    5   1       1000            0    424.4kb        424.4kb

搜索API

ES提供了两种搜索的方式:请求参数方式请求体方式

请求参数方式

curl 'localhost:9200/bank/_search?q=*&pretty'

其中bank是查询的索引名称,q后面跟着搜索的条件:q=*表示查询所有的内容

请求体方式(推荐这种方式)

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match_all": {} }
}'

这种方式会把查询的内容放入body中,会造成一定的开销,但是易于理解。在平时的练习中,推荐这种方式。

 

返回的内容

复制代码
{
  "took" : 26,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1000,
    "max_score" : 1.0,
    "hits" : [ {
      "_index" : "bank",
      "_type" : "account",
      "_id" : "1",
      "_score" : 1.0, "_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"}
    }, {
      "_index" : "bank",
      "_type" : "account",
      "_id" : "6",
      "_score" : 1.0, "_source" : {"account_number":6,"balance":5686,"firstname":"Hattie","lastname":"Bond","age":36,"gender":"M","address":"671 Bristol Street","employer":"Netagy","email":"hattiebond@netagy.com","city":"Dante","state":"TN"}
    }, {
      "_index" : "bank",
      "_type" : "account",
      "_id" : "13",
复制代码

返回的内容大致可以如下讲解:

took:是查询花费的时间,毫秒单位

time_out:标识查询是否超时

_shards:描述了查询分片的信息,查询了多少个分片、成功的分片数量、失败的分片数量等

hits:搜索的结果,total是全部的满足的文档数目,hits是返回的实际数目(默认是10)

_score是文档的分数信息,与排名相关度有关,参考各大搜索引擎的搜索结果,就容易理解。 

由于ES是一次性返回所有的数据,因此理解返回的内容是很必要的。它不像传统的SQL是先返回数据的一个子集,再通过数据库端的游标不断的返回数据(由于对传统的数据库理解的不深,这里有错还望指正)。

查询语言DSL

ES支持一种JSON格式的查询,叫做DSL,domain specific language。这门语言刚开始比较难理解,因此通过几个简单的例子开始:

下面的命令,可以搜索全部的文档:

{
  "query": { "match_all": {} }
}

query定义了查询,match_all声明了查询的类型。还有其他的参数可以控制返回的结果:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match_all": {} },
  "size": 1
}'

上面的命令返回了所有文档数据中的第一条文档。如果size不指定,那么默认返回10条。

 

下面的命令请求了第10-20的文档。

复制代码
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match_all": {} },
  "from": 10,
  "size": 10
}'
复制代码

 

下面的命令指定了文档返回的排序方式:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match_all": {} },
  "sort": { "balance": { "order": "desc" } }
}'

 

执行搜索

上面了解了基本的搜索语句,下面就开始深入一些常用的DSL了。

之前的返回数据都是返回文档的所有内容,这种对于网络的开销肯定是有影响的,下面的例子就指定了返回特定的字段:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match_all": {} },
  "_source": ["account_number", "balance"]
}'

再回到query,之前的查询都是查询所有的文档,并不能称之为搜索引擎。下面就通过match方式查询特定字段的特定内容,比如查询余额为20的账户信息:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match": { "account_number": 20 } }
}'

查询地址为mill的信息:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match": { "address": "mill" } }
}'

查询地址为mill或者lane的信息:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match": { "address": "mill lane" } }
}'

如果我们想要返回同时包含mill和lane的,可以通过match_phrase查询:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match_phrase": { "address": "mill lane" } }
}'

ES提供了bool查询,可以把很多小的查询组成一个更为复杂的查询,比如查询同时包含mill和lane的文档:

复制代码
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": {
    "bool": {
      "must": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}'
复制代码

修改bool参数,可以改为查询包含mill或者lane的文档:

复制代码
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": {
    "bool": {
      "should": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}'
复制代码

也可以改写为must_not,排除包含mill和lane的文档:

复制代码
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": {
    "bool": {
      "must_not": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}'
复制代码

bool查询可以同时使用must, should, must_not组成一个复杂的查询:

复制代码
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": {
    "bool": {
      "must": [
        { "match": { "age": "40" } }
      ],
      "must_not": [
        { "match": { "state": "ID" } }
      ]
    }
  }
}'
复制代码

过滤查询

之前说过score字段指定了文档的分数,使用查询会计算文档的分数,最后通过分数确定哪些文档更相关,返回哪些文档。

有的时候我们可能对分数不感兴趣,就可以使用filter进行过滤,它不会去计算分值,因此效率也就更高一些。

filter过滤可以嵌套在bool查询内部使用,比如想要查询在2000-3000范围内的所有文档,可以执行下面的命令:

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

ES除了上面介绍过的范围查询range、match_all、match、bool、filter还有很多其他的查询方式,这里就先不一一说明了。

聚合

聚合提供了用户进行分组和数理统计的能力,可以把聚合理解成SQL中的GROUP BY和分组函数。在ES中,你可以在一次搜索查询的时间内,即完成搜索操作也完成聚合操作,这样就降低了多次使用REST API造成的网络开销。

下面就是通过terms聚合的简单样例:

复制代码
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "size": 0,
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state"
      }
    }
  }
}'
复制代码

它类似于SQL中的下面的语句:

SELECT state, COUNT(*) FROM bank GROUP BY state ORDER BY COUNT(*) DESC

返回的数据:

复制代码
"hits" : {
    "total" : 1000,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "group_by_state" : {
      "buckets" : [ {
        "key" : "al",
        "doc_count" : 21
      }, {
        "key" : "tx",
        "doc_count" : 17
      }, {
        "key" : "id",
        "doc_count" : 15
      }, {
        "key" : "ma",
        "doc_count" : 15
      }, {
        "key" : "md",
        "doc_count" : 15
      }, {
        "key" : "pa",
        "doc_count" : 15
      }, {
        "key" : "dc",
        "doc_count" : 14
      }, {
        "key" : "me",
        "doc_count" : 14
      }, {
        "key" : "mo",
        "doc_count" : 14
      }, {
        "key" : "nd",
        "doc_count" : 14
      } ]
    }
  }
}
复制代码

由于size设置为0,它并没有返回文档的信息,只是返回了聚合的结果。

比如统计不同账户状态下的平均余额:

复制代码
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "size": 0,
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state"
      },
      "aggs": {
        "average_balance": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}'
复制代码

聚合支持嵌套,举个例子,先按范围分组,在统计不同性别的账户余额:

复制代码
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "size": 0,
  "aggs": {
    "group_by_age": {
      "range": {
        "field": "age",
        "ranges": [
          {
            "from": 20,
            "to": 30
          },
          {
            "from": 30,
            "to": 40
          },
          {
            "from": 40,
            "to": 50
          }
        ]
      },
      "aggs": {
        "group_by_gender": {
          "terms": {
            "field": "gender"
          },
          "aggs": {
            "average_balance": {
              "avg": {
                "field": "balance"
              }
            }
          }
        }
      }
    }
  }
}'
复制代码

聚合可以实现很多复杂的功能,而且ES也提供了很多复杂的聚合,这里作为引导篇,也不过多介绍了。

 

对于基本的数据搜索大致就是上面讲述的样子,熟悉了一些常用的API,入门还是很简单的,倒是要熟练使用ES,还是需要掌握各种搜索查询的命令,以及ES内部的原理。

ES(Elasticsearch)是一个分布式、RESTful 风格的搜索和数据分析引擎,它基于Lucene构建,其核心数据结构主要围绕索引、文档、字段等概念展开,以下是详细介绍: ### 索引(Index) 索引是Elasticsearch中数据存储和检索的最高级逻辑容器,类似于关系型数据库中的“数据库”。一个索引可以包含大量的文档,并且每个索引都有其特定的配置,如分片数、副本数、映射(Mapping)等。例如,在一个电商系统中,可以创建一个名为“products”的索引来存储所有商品的信息。 ### 分片(Shard) 由于单个节点的存储和计算能力有限,Elasticsearch将索引数据分割成多个分片,分布在集群中的不同节点上。分片分为主分片(Primary Shard)和副本分片(Replica Shard)。主分片负责数据的写入和更新操作,副本分片是主分片的复制,提供数据的冗余备份,提高系统的可用性和读取性能。例如,一个索引可以配置5个主分片和1个副本分片,这样总共就有10个分片(5个主分片和5个副本分片)分布在集群中。 ### 文档(Document) 文档是Elasticsearch中可被索引的基本单位,类似于关系型数据库中的“行”。每个文档都有一个唯一的ID,可以是自动生成的,也可以由用户指定。文档以JSON格式存储,包含多个字段,每个字段都有其特定的数据类型,如文本、数字、日期等。例如,一个商品文档可以包含“name”(商品名称)、“price”(价格)、“description”(描述)等字段。 ### 字段(Field) 字段是文档中的属性,每个字段都有其对应的数据类型。Elasticsearch支持多种数据类型,如: - **文本类型(Text)**:用于存储全文搜索的文本数据,会进行分词处理。例如,商品描述字段可以使用文本类型。 - **关键字类型(Keyword)**:用于存储精确匹配的字符串数据,不会进行分词处理。例如,商品ID字段可以使用关键字类型。 - **数字类型(Integer、Long、Float、Double)**:用于存储各种数值数据。 - **日期类型(Date)**:用于存储日期和时间数据。 ### 映射(Mapping) 映射定义了索引中字段的数据类型、分词器、索引选项等属性。它类似于关系型数据库中的“表结构”。可以在创建索引时显式定义映射,也可以让Elasticsearch自动推断字段的类型(动态映射)。例如,可以定义一个名为“products”的索引的映射,指定“name”字段为文本类型,使用“ik_max_word”分词器,“price”字段为浮点数类型等。 ### 倒排索引(Inverted Index) 倒排索引是Elasticsearch实现高效搜索的核心数据结构。它记录了每个词项(Term)出现在哪些文档中,以及在文档中的位置等信息。当用户进行搜索时,Elasticsearch会根据倒排索引快速定位到包含搜索词项的文档。例如,当搜索“手机”时,倒排索引会返回所有包含“手机”这个词项的文档ID,然后Elasticsearch可以根据其他条件(如相关性、排序等)对这些文档进行进一步处理和返回。 ```python # 以下是一个简单的Python代码示例,展示如何使用Elasticsearch的Python客户端创建索引和添加文档 from elasticsearch import Elasticsearch # 创建Elasticsearch客户端 es = Elasticsearch(["http://localhost:9200"]) # 创建索引并定义映射 index_name = "products" mapping = { "mappings": { "properties": { "name": {"type": "text", "analyzer": "ik_max_word"}, "price": {"type": "float"}, "description": {"type": "text", "analyzer": "ik_max_word"} } } } es.indices.create(index=index_name, body=mapping) # 添加文档 doc = { "name": "苹果手机", "price": 5999.0, "description": "最新款苹果手机,性能强劲" } es.index(index=index_name, id=1, body=doc) ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值