原英文版地址: https://www.elastic.co/guide/en/elasticsearch/reference/7.7/getting-started-search.html, 原文档版权归 www.elastic.co 所有
本地英文版地址: ../en/getting-started-search.html

开始搜索

一旦你往一个 Elasticsearch 索引中导入了一些数据,你就可以发送请求到终端 _search 来搜索数据。 要访问完整的搜索功能套件,要使用 ElasticSearch 的 QUERY DSL 在请求体中指定搜索条件。 在请求 URI 中指定要搜索的索引的名称。

比如,下面这个请求获取索引 bank 中的所有文档,并按 账号(account number) 排序:

GET /bank/_search
{
  "query": { "match_all": {} },
  "sort": [
    { "account_number": "asc" }
  ]
}

默认情况下,响应的 hits 部分包含匹配搜索条件的前 10 个文档。

{
  "took" : 63,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
        "value": 1000,
        "relation": "eq"
    },
    "max_score" : null,
    "hits" : [ {
      "_index" : "bank",
      "_type" : "_doc",
      "_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" : "_doc",
      "_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花费了多少时间去执行查询,单位 毫秒
  • timed_out – 搜索请求是否超时
  • _shards – 搜索了多少个分片,以及有多少个分片成功、失败或被跳过。
  • max_score – 找到的最相关的文档的评分
  • hits.total.value - 找到了多少个匹配的文档
  • hits.sort - 文档的排序位置(当不按相关性得分排序时)
  • hits._score - 文档的相关性评分(在使用 match_all 时不适用)

每个搜索请求都是独立的(self-contained):ElasticSearch不会在请求之间维护任何状态信息。 要按页浏览搜索命中,在请求参数中指定 from and size 参数。

比如,下面的请求得到命中的 10 到 19 个结果:

GET /bank/_search
{
  "query": { "match_all": {} },
  "sort": [
    { "account_number": "asc" }
  ],
  "from": 10,
  "size": 10
}

既然你已经了解了如何提交基本的搜索请求,就可以开始构建比 match_all 更有趣的查询了。

若要在字段中搜索特定的词项,可以使用 match 查询。 例如,以下请求在字段 address 中搜索地址包含 milllane 的客户:

GET /bank/_search
{
  "query": { "match": { "address": "mill lane" } }
}

若要执行 短语搜索 (phrase search) 而不是匹配单个词项,请使用 match_phrase 而不是 match。 比如,下面这个搜索只匹配地址包含短语 mill lane 的:

GET /bank/_search
{
  "query": { "match_phrase": { "address": "mill lane" } }
}

要构建更复杂的查询,可以使用 bool 查询去合并多个查询条件。 你可以根据 需要(必须匹配, must match)、期望(应该匹配, should match)或不希望(必须不匹配, must not match) 指定条件。

比如,以下请求在索引 bank 中搜索 客户年龄是 40 岁,但不包括居住在 Idaho(ID) 的客户的帐户:

GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "age": "40" } }
      ],
      "must_not": [
        { "match": { "state": "ID" } }
      ]
    }
  }
}

布尔查询中的每个 mustshouldmust_not 元素都称为查询子句。 文档在每个 mustshould 子句中满足条件的程度,决定了文档的 相关性评分(relevance score)。 得分越高,文档与条件的匹配度越高。 默认情况下,Elasticsearch 返回的文档按这些相关性得分排序。

条件中的 must_not 字句被看成是一个 过滤器(filter) 。 它影响文档是否包含在结果中,但不参与文档的评分。 还可以显式指定任意过滤器,以包含或排除基于结构化数据的文档。

例如,下面的请求使用一个范围过滤器去将结果限制在 余额在$20,000 到 $30,000(含) 之间的账户。

GET /bank/_search
{
  "query": {
    "bool": {
      "must": { "match_all": {} },
      "filter": {
        "range": {
          "balance": {
            "gte": 20000,
            "lte": 30000
          }
        }
      }
    }
  }
}