ElasticSearch的基本操作

1、索引相关操作(类似数据库)

1.1、创建索引

对比关系型数据库,创建索引就等同于创建数据库。

向 ES 服务器发 PUT 请求 :http://127.0.0.1:9200/shopping,shopping 即为索引名。

请求后,服务器返回响应如下:

说明如下:

  1. {
  2. "acknowledged"【响应结果】: true, # true 操作成功
  3. "shards_acknowledged"【分片结果】: true, # 分片操作成功
  4. "index"【索引名称】: "shopping"
  5. }
  6. # 注意:创建索引库的分片数默认 1 片,在 7.0.0 之前的 Elasticsearch 版本中,默认 5 片

如果重复添加索引,会返回错误信息,如下:

 

1.2、查询索引

1.2.1、查询所有索引

向 ES 服务器发 GET 请求:http://127.0.0.1:9200/_cat/indices?v

这里请求路径中的_cat 表示查看的意思,indices 表示索引,所以整体含义就是查看当前 ES 服务器中的所有索引,就好像 MySQL 中的 show tables 的感觉。

当 ES服务器中没有索引时,响应结果如下:

在成功创建索引后,再查询所有索引,可以看到以下示例结果:

 

1.2.2、查询单个索引

向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/shopping ,后面的 shopping 指的是索引名。查看索引和创建索引向 ES 服务器发送的请求路径都是一致的,但是 HTTP 方法不一致。
请求后,服务器响应结果如下:

 

返回结果说明如下:

  1. {
  2. "shopping"【索引名】: {
  3. "aliases"【别名】: {},
  4. "mappings"【映射】: {},
  5. "settings"【设置】: {
  6. "index"【设置 - 索引】: {
  7. "creation_date"【设置 - 索引 - 创建时间】: "1614265373911",
  8. "number_of_shards"【设置 - 索引 - 主分片数量】: "1",
  9. "number_of_replicas"【设置 - 索引 - 副分片数量】: "1",
  10. "uuid"【设置 - 索引 - 唯一标识】: "eI5wemRERTumxGCc1bAk2A",
  11. "version"【设置 - 索引 - 版本】: {
  12. "created": "7080099"
  13. },
  14. "provided_name"【设置 - 索引 - 名称】: "shopping"
  15. }
  16. }
  17. }
  18. }

 

1.3、删除索引

向 ES 服务器发 DELETE 请求 :http://127.0.0.1:9200/shopping,后面的 shopping 指的是索引名。
结果如下:

 

删除后重新访问索引时,服务器返回响应提示索引不存在,如下:

 

2、文档相关操作(类似行)

2.1、创建文档

这里的文档可以类比为关系型数据库中的表数据,添加的数据格式为 JSON 格式。

创建文档,并添加数据,向 ES 服务器发 POST 请求 :http://127.0.0.1:9200/shopping/_doc,shopping 指的是索引名。如果在创建文档时,该索引不存在,ES 会默认帮你新建索引。

请求体内容为: 

  1. {
  2. "title":"小米手机",
  3. "category":"小米",
  4. "images":"http://www.gulixueyuan.com/xm.jpg",
  5. "price":3999.00
  6. }

(此处发送请求的方式必须为 POST,不能是 PUT,否则会报错。)

服务器响应结果如下: 

 

结果说明如下:

  1. {
  2. "_index"【索引】: "shopping",
  3. "_type"【类型-文档】: "_doc",
  4. "_id"【唯一标识】: "Xhsa2ncBlvF_7lxyCE9G", #可以类比为 MySQL 中的主键,随机生成
  5. "_version"【版本】: 1,
  6. "result"【结果】: "created", #这里的 create 表示创建成功
  7. "_shards"【分片】: {
  8. "total"【分片 - 总数】: 2,
  9. "successful"【分片 - 成功】: 1,
  10. "failed"【分片 - 失败】: 0
  11. },
  12. "_seq_no": 0,
  13. "_primary_term": 1
  14. }
上面的数据创建后,由于没有指定数据唯一性标识(ID),默认情况下,ES 服务器会随机生成一个ID,即上面返回结果中的 “_id”。 

 

如果想要自定义唯一性标识,可以在创建文档时指定,如:http://127.0.0.1:9200/shopping/_doc/1001,1001即为指定的该文档的 id。此时请求方式既可以是 POST,也可以是 PUT。

 

2.2、查看文档

2.2.1、查询指定id文档

查看文档时,可以指明文档的唯一性标识,类似于 MySQL 中数据的主键查询。向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/shopping/_doc/1001,响应结果如下:

 

2.2.2、查询所有文档

向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/shopping/_search,响应结果如下:

 

2.3、修改文档

2.3.1、全量修改

修改文档和新增文档的 URL 地址一样,如果请求体变化,会将原有的数据内容全部覆盖。向 ES 服务器发 POST 请求 :http://127.0.0.1:9200/shopping/_doc/1001,请求体内容为:

  1. {
  2. "title":"华为手机",
  3. "category":"华为",
  4. "images":"http://www.gulixueyuan.com/hw.jpg",
  5. "price":4999.00
  6. }

响应结果如下:

修改后再次查询该文档内容,可以发现,文档已经被修改。

 

2.3.2、局部修改(修改部分字段)

修改数据时,也可以只修改某一给条数据的局部信息,向 ES 服务器发 POST 请求 :http://127.0.0.1:9200/shopping/_update/1001,请求体内容为: 

  1. {
  2. "doc": {
  3. "title": "修改后title",
  4. "price":3000.00
  5. }
  6. }

响应结果如下:

修改后再次查询该文档内容,可以发现,该文档对应的字段已经被修改成功。

 

2.4、删除文档

2.4.1、删除指定id文档

删除文档向 ES 服务器发 DELETE 请求 :http://127.0.0.1:9200/shopping/_doc/1001,响应结果如下:

 

响应结果说明如下:

 

删除后再查询当前文档信息,响应结果如下:

如果删除一个不存在的文档,结果会提示not found。

 

2.4.2、根据条件删除文档

一般删除数据都是根据文档的唯一性标识进行删除,实际操作时,也可以根据条件对多条数据进行删除。

比如有以下多个文档:

  1. {
  2. "title":"小米手机",
  3. "category":"小米",
  4. "images":"http://www.gulixueyuan.com/xm.jpg",
  5. "price":4000.00
  6. }
  7. {
  8. "title":"华为手机",
  9. "category":"华为",
  10. "images":"http://www.gulixueyuan.com/hw.jpg",
  11. "price":4000.00
  12. }

向 ES 服务器发 POST 请求 :http://127.0.0.1:9200/shopping/_delete_by_query,请求体内容为:

  1. {
  2. "query":{
  3. "match":{
  4. "price":4000.00
  5. }
  6. }
  7. }

删除成功后,服务器响应结果: 

响应结果说明如下:

  1. {
  2. "took"【耗时】: 175,
  3. "timed_out"【是否超时】: false,
  4. "total"【总数】: 2,
  5. "deleted"【删除数量】: 2,
  6. "batches": 1,
  7. "version_conflicts": 0,
  8. "noops": 0,
  9. "retries": {
  10. "bulk": 0,
  11. "search": 0
  12. },
  13. "throttled_millis": 0,
  14. "requests_per_second": -1.0,
  15. "throttled_until_millis": 0,
  16. "failures": []
  17. }

 

3、映射关系(mapping)

3.1、默认映射(动态映射 Dynamic mapping)

在Elasticsearch中,动态映射是指 Elasticsearch 根据数据自动创建字段和类型的过程。默认情况下,当你索引一个文档,Elasticsearch会检查文档的字段,并相应地更新映射。

动态映射可以通过以下方式进行控制:

1)使用dynamic参数:

  • true(默认值):允许动态添加新字段。
  • false:不允许动态添加新字段,但会继续索引现有字段。
  • strict:如果尝试动态添加新字段,则索引操作将失败。

2)使用dynamic_templates可自定义动态添加字段和映射的规则。

 

示例,以下是一个索引设置,它禁止动态添加新字段,但允许现有字段被动态映射:

  1. PUT my_index
  2. {
  3. "mappings": {
  4. "dynamic": false,
  5. "properties": {
  6. "name": {
  7. "type": "text"
  8. },
  9. "date": {
  10. "type": "date"
  11. }
  12. }
  13. }
  14. }

以下是使用dynamic_templates的例子,以下配置指定了对所有字符串字段使用keyword子字段的动态映射:

  1. PUT my_index
  2. {
  3. "mappings": {
  4. "dynamic_templates": [
  5. {
  6. "strings_as_keywords": {
  7. "match_mapping_type": "string",
  8. "mapping": {
  9. "type": "keyword"
  10. }
  11. }
  12. }
  13. ],
  14. "properties": {
  15. "name": {
  16. "type": "text"
  17. },
  18. "date": {
  19. "type": "date"
  20. }
  21. }
  22. }
  23. }

如果你尝试索引一个新的文档,并且文档中包含了没有在映射中定义的字段,Elasticsearch将使用默认的规则或你自定义的规则来确定字段的类型并创建映射。如果你想要改变这些默认的映射行为,可以在创建索引时指定该索引的映射关系。

 

3.2、创建映射关系

创建mapping映射类似于我们创建表结构(规定字段什么类型,多长等基本信息),而映射关系会规定索引中的字段是否可以分词、是否可以索引查询等信息。

映射数据说明:

  • 字段名
  • type:类型,Elasticsearch 中支持的数据类型非常丰富,说几个关键的:
    • String 类型,又分两种:1)text:可分词;2)keyword:不可分词,数据会作为完整字段进行匹配
    • Numerical:数值类型,分两类基本数据类型:long、integer、short、byte、double、float、half_float。浮点数的高精度类型:scaled_float
    • Date:日期类型
    • Array:数组类型
    • Object:对象
  • index:是否索引,即该字段是否可被搜索出来。默认为 true,也就是说默认所有字段都会被索引。true:字段会被索引,则可以用来进行搜索,false:字段不会被索引,不能用来搜索
  • store:是否将数据进行独立存储,默认为 false。原始的文本会存储在_source 里面,默认情况下其他提取出来的字段都不是独立存储的,是从_source 里面提取出来的。当然你也可以独立的存储某个字段,只要设置"store": true 即可,获取独立存储的字段要比从_source 中解析快得多,但是也会占用更多的空间,所以要根据实际业务需求来设置。
  • analyzer:分词器

示例,先创建索引 PUT http://127.0.0.1:9200/user,然后发出带 json 请求体的 put 请求创建映射关系 PUT http://127.0.0.1:9200/user/_mapping,请求体如下:

  1. {
  2. "properties":{
  3. "name":{
  4. "type":"text", // text 文本 可以分词
  5. "index":true // 可以索引查询
  6. },
  7. "sex":{
  8. "type":"keyword", // 不可以分词
  9. "index":true
  10. },
  11. "tel":{
  12. "type":"keyword", // 不可以分词
  13. "index":false //不可以索引查询
  14. }
  15. }
  16. }

创建示例文档 POST http://127.0.0.1:9200/user/_doc/1001

  1. {
  2. "name":"小花",
  3. "sex":"",
  4. "tel":"123456"
  5. }

此时我们做下查询,GET http://127.0.0.1:9200/user/_search ,请求体:

  1. {
  2. "query":{
  3. "match":{
  4. "sex":"男的"
  5. }
  6. }
  7. }

会发现没有查到数据,因为 mapping 限制的 sex 为 keyword,所以 sex 查询条件不会被分词也就匹配不到文档数据。

再发出请求 GET http://127.0.0.1:9200/user/_search,请求体:

  1. {
  2. "query":{
  3. "match":{
  4. "tel":"123456"
  5. }
  6. }
  7. }

响应如下:

可以发信息查询报错了,因为映射关系中配置 tel 的 index 为 false,即没有索引不支持查询。

 

3.2.1、ES设置字段既可以精准查询又可以分词查询

在ES中,精准查询的字段必须不为text类型,因为text类型的字段在查询中时可以被es进行分词查询的,这与精准查询矛盾。

如果一个字段我们既想要可以精准查询,又想要可以分词查询,此时我们可以通过定义不同的字段类型来实现同一个字段既可以精准查询又可以分词查询。具体来说,你可以使用keyword子字段配合文本字段来实现这一需求。

以下是一个创建索引的例子,其中展示了如何定义一个可精准查询同时也可以分词查询的字段:

  1. PUT my_index
  2. {
  3. "mappings": {
  4. "properties": {
  5. "my_field": {
  6. "type": "text",
  7. "fields": {
  8. "keyword": {
  9. "type": "keyword",
  10. "ignore_above": 256
  11. }
  12. }
  13. }
  14. }
  15. }
  16. }

在这个例子中,my_field是一个文本字段,可以进行分词查询。同时,它还有一个my_field.keyword的子字段,这个子字段是keyword类型,可以进行精准查询。

精准查询示例(精确匹配整个词汇):

  1. GET my_index/_search
  2. {
  3. "query": {
  4. "term": {
  5. "my_field.keyword": {
  6. "value": "exactValue"
  7. }
  8. }
  9. }
  10. }

分词查询示例(分析词汇进行匹配):

  1. GET my_index/_search
  2. {
  3. "query": {
  4. "match": {
  5. "my_field": "part of value"
  6. }
  7. }
  8. }

这样,同一个字段my_field既可以进行精确查询,也可以进行分词查询。

 

posted @ 2023-01-11 19:43  wenxuehai  阅读(629)  评论(0编辑  收藏  举报
//右下角添加目录