插入数据
一旦你启动并运行集群,你就可以创建数据了。Elasticsearch 有多种方式插入数据,但最终它们都执行同样的操作,将 JSON 文档放入 Elasticsearch 索引中。

你可以使用简单的 PUT 请求去执行操作,请求须指定文档的索引名称,唯一的文档 ID,以及请求体中一个或多个键值对。

PUT /customer/_doc/1
{
  "name": "John Doe"
}

这个请求(如不存在)将自动创建一个 ID 为 1 的新文档,并储存键值对,并为其建立索引。

由于这是一个新文档,返回的结果显示新创建的文档版本号为 1:

{
  "_index" : "customer",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "failed" : 0
  },
  "_seq_no" : 26,
  "_primary_term" : 4
}

你可以在集群里任意节点去获取文档,你也可以 GET 请求指定 ID 文档

GET /customer/_doc/1

返回结果显示找到里对应的指定文档,并返回了原始字段信息

{
  "_index" : "customer",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 26,
  "_primary_term" : 4,
  "found" : true,
  "_source" : {
    "name": "John Doe"
  }
}

批量插入数据
如果有大量的文档需要插入,你可以使用 BULK API 批量插入数据。使用 Bulk API 要比单独请求提交要快,是因为它最大限度地减少了网络传输次数。

最佳批量插入大小取决于许多因素:文档大小和复杂性、索引、搜索负载以及集群的可用资源。每次批量处理最好在 1000 ~ 5000 个文档,文档大小最好是在 5M ~ 15M 之间。

将数据批量导入 Elasticsearch,你就可以开始搜索和分析了。
下载 acounts.jsondemo数据。随机生成的 demo 数据展示了以下的用户信息:

{
    "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"
}

使用_bulk 请求将账户数据导入到银行文档中:

curl -H "Content-Type: application/json" -XPOST "localhost:9200/bank/_bulk?pretty&refresh" --data-binary "@C:/user/accounts.json


注意:
@C:/user/accounts.json,是该文件再你电脑中的存储位置

返回结果显示了成功导入了 1000 个文档


" curl "localhost:9200/_cat/indices?v"

health status index uuid pri rep docs.count docs.deleted store.size pri.store.size yellow open bank l7sSYV2cQXmu6_4rJWVIww
5 1 1000 0 128.6kb 128.6kb

搜索

一旦你开始在 Elasticsearch 插入数据,你就可以通过_search 方式发送请求来进行搜索,如果使用匹配搜索功能,在请求体中使用 Elasticsearch Query DSL 指定搜索条件。你也可以在请求头指定要搜索的索引名称。

如下图所示:搜索银行索引中,所有账号按照 account_number 排序:

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

默认情况下,会返回符合条件搜索的前 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 – 查询花费时长(毫秒)
timed_out – 请求是否超时
_shards – 搜索了多少分片,成功、失败或者跳过了多个分片(明细)
max_score – 最相关的文档分数
hits.total.value - 找到的文档总数
hits.sort - 文档排序方式 (如没有则按相关性分数排序)
hits._score - 文档的相关性算分 (match_all 没有算分)

 每个搜索请求都是独立的:Elasticsearch 不维护任何请求中的状态信息。如果做分页的话,请在请求中指定 From 和 Size 参数。
如图所示:搜索第 10 到 19 的数据

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

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

想搜索特定的字段,可以使用匹配查询。如下所示,请求搜索地址字段以查询地址中包含 mill 或 lane 的客户

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

如果要全部匹配而不是仅仅是包含关键字之一,你需要使用 match_phrase 而不是 match。(译者注:match 和 match_phrase 的区别就像是 or 和 and 的区别) 如图所示:

在请求中查询地址中同时包含 mill 和 lane 的客户:

 

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

如果要构造更复杂的查询,可以使用布尔查询来组合多个查询条件,must match、should match、must not match

如图所示:请求在银行索引里搜索年龄是 40 的,但不居住在爱达荷州 (ID) 的客户:

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

布尔查询中每个 must,should,must_not 都被称为查询子句。每个
must 或者 should 查询子句中的条件都会影响文档的相关得分。得分越高,文档跟搜索条件匹配得越好。默认情况下,Elasticsearch 返回的文档会根据相关性算分倒序排列。

must_not 子句中认为是过滤条件。它会过滤返回结果,但不会影响文档的相关性算分,你还可以明确指定任意过滤条件去筛选结构化数据文档。

如图所示:请求搜索余额在 20000 ~ 30000(包括 30000) 之间的账户

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

 使用聚合分析

Elasticsearch 聚合让你看到一些有关搜索结果元信息,返回结果能显示例如:“德克萨斯州有多少个开户的人?” 或者 “田纳西州的平均帐户余额是多少?”。你可以搜索文档,过滤 hits,使用聚合去分析并返回结果。

如图所示:请求使用 terms 聚合对 bank 索引中对所有还在账户进行分组,并安装返回前 10 个账户数最多的州:

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state.keyword"
      }
    }
  }
}
{
  "took": 29,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped" : 0,
    "failed": 0
  },
  "hits" : {
     "total" : {
        "value": 1000,
        "relation": "eq"
     },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "group_by_state" : {
      "doc_count_error_upper_bound": 20,
      "sum_other_doc_count": 770,
      "buckets" : [ {
        "key" : "ID",
        "doc_count" : 27
      }, {
        "key" : "TX",
        "doc_count" : 27
      }, {
        "key" : "AL",
        "doc_count" : 25
      }, {
        "key" : "MD",
        "doc_count" : 25
      }, {
        "key" : "TN",
        "doc_count" : 23
      }, {
        "key" : "MA",
        "doc_count" : 21
      }, {
        "key" : "NC",
        "doc_count" : 21
      }, {
        "key" : "ND",
        "doc_count" : 21
      }, {
        "key" : "ME",
        "doc_count" : 20
      }, {
        "key" : "MO",
        "doc_count" : 20
      } ]
    }
  }
}{
  "took": 29,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped" : 0,
    "failed": 0
  },
  "hits" : {
     "total" : {
        "value": 1000,
        "relation": "eq"
     },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "group_by_state" : {
      "doc_count_error_upper_bound": 20,
      "sum_other_doc_count": 770,
      "buckets" : [ {
        "key" : "ID",
        "doc_count" : 27
      }, {
        "key" : "TX",
        "doc_count" : 27
      }, {
        "key" : "AL",
        "doc_count" : 25
      }, {
        "key" : "MD",
        "doc_count" : 25
      }, {
        "key" : "TN",
        "doc_count" : 23
      }, {
        "key" : "MA",
        "doc_count" : 21
      }, {
        "key" : "NC",
        "doc_count" : 21
      }, {
        "key" : "ND",
        "doc_count" : 21
      }, {
        "key" : "ME",
        "doc_count" : 20
      }, {
        "key" : "MO",
        "doc_count" : 20
      } ]
    }
  }
}

如图所示:在返回结果中 buckets 的值是字段 state 的桶。 doc_count 表示每州的账户数。你可以看到爱达荷州中有 27 个帐户,由于 "size": 0 表示了返回只有聚合结果,无具体数据。

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state.keyword"
      },
      "aggs": {
        "average_balance": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}

你可以使用组合聚合来构建更为复杂的统计数据。如图所示:请求将 avg 聚合嵌套在 group_by_state 聚合内,以计算每州的平均账户余额

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state.keyword"
      },
      "aggs": {
        "average_balance": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}

如图所示:你也可以不按内置结果进行排序,而可以使用聚合后的 average_balance 字段进行排序

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state.keyword",
        "order": {
          "average_balance": "desc"
        }
      },
      "aggs": {
        "average_balance": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}

除了这些基本的桶跟指标聚合之外,Elasticsearch 还提供了其他类型的聚合,用于对多个字段进行操作和分析特定类型的数据,如日期、IP 和地理数据。你还可以将单个聚合的结果送到管道聚合中进行深一步分析。

 

posted on 2022-05-04 13:08  輪滑少年  阅读(1126)  评论(0编辑  收藏  举报