• Elasticsearch索引操作(七)


            索引的相关操作,涉及创建、删除、关闭和打开索引,以及索引别名的操作。其中,索引别名的操作在生产环境中使用比较广泛,可以和关闭或删除索引配合使用。在生产环境中使用索引时,一定要慎重操作,因为稍有不慎就会导致数据的丢失或异常。

    创建索引

            使用ES构建搜索引擎的第一步是创建索引。在创建索引时,可以按照实际需求对索引进行主分片和副分片设置。ES创建索引的请求类型为PUT,其请求形式如下:

    1. PUT /${index_name}
    2. {
    3. "settings": {
    4. ...
    5. }
    6. , "mappings": {
    7. ...
    8. }
    9. }

            其中:变量index_name就是创建的目标索引名称;可以在settings子句内部填写索引相关的设置项,如主分片个数和副分片个数等;可以在mappings子句内部填写数据组织结构,即数据映射。

    ES创建索引时,主分片默认个数为5,副分片个数为0,如果我们要设置主分片个数为15,副分片个数为2,则相应的DSL如下:

    1. PUT /hotel
    2. {
    3. "settings": {
    4. "number_of_shards": 15, //指定主分片个数
    5. "number_of_replicas": 2 //指定副分片个数
    6. }
    7. , "mappings": {
    8. "properties": {
    9. ...
    10. }
    11. }
    12. }

    删除索引

    ES中删除索引的请求类型是DELETE,其请求形式如下:

    DELETE /${index_name}

    关闭索引

            在有些场景下,某个索引暂时不使用,但是后期可能又会使用,这里的使用是指数据写入和数据搜索。这个索引在某一时间段内属于冷数据或者归档数据,这时可以使用索引的关闭功能。索引关闭时,只能通过ES的API或者监控工具看到索引的元数据信息,但是此时该索引不能写入和搜索数据,待该索引被打开后,才能写入和搜索数据。

    关闭索引的请求形式如下:

    POST /${index_name}/_close

    比如以下案例:

    以上执行响应如下:

     

     此时新增一条数据:

    此时结果响应如下:

             同理,此时搜索hotel索引,请求返回的信息也会和以上返回的是同样的,即索引在关闭时不能提供搜索服务

    打开索引

            索引关闭后,需要开启读写服务时可以将其设置为打开状态。下面的示例是把处于关闭状态的hotel索引设置为打开状态。

    索引被打开后,就可以对其进行读写操作了

    索引别名

            别名是指给一个或者多个索引定义另外一个名称,使索引别名和索引之间可以建立某种逻辑关系。

            可以用别名表示别名和索引之间的包含关系。例如,我们建立了1月、2月、3月的用户入住旅馆的日志索引,假设当前日期是4月1日,需要搜索过去的3个月的日志索引,如果分别去3个索引中进行搜索,这种编码方案比较低效。此时可以创建一个别名last_three_month,设置前面的3个索引的别名为last_three_month,然后在last_three_month中进行搜索即可。

            如下图所示,last_three_month包含january_log、february_log和march_log3个索引,用户请求在last_three_month中进行搜索时,ES会在上述3个索引中进行搜索。

     比如看一下案例,首先依次建立january_log、february_log和march_log3个索引。创建索引january_log的DSL如下:

    1. POST /january_log/_doc/001
    2. {
    3. "uid":"001",
    4. "hotel_id":"12345",
    5. "createDate":"2021-01-05"
    6. }
    7. POST /february_log/_doc/001
    8. {
    9. "uid":"001",
    10. "hotel_id":"23456",
    11. "createDate":"2021-02-05"
    12. }
    13. POST /march_log/_doc/001
    14. {
    15. "uid":"001",
    16. "hotel_id":"34567",
    17. "createDate":"2021-03-05"
    18. }

     现在建立别名last_three_month,设置上面3个索引的别名为last_three_month,请求的DSL如下:

    1. POST /_aliases
    2. {
    3. "actions": [
    4. {
    5. "add": {
    6. "index": "january_log",
    7. "alias": "last_three_month"
    8. }
    9. },
    10. {
    11. "add": {
    12. "index": "february_log",
    13. "alias": "last_three_month"
    14. }
    15. },
    16. {
    17. "add": {
    18. "index": "march_log",
    19. "alias": "last_three_month"
    20. }
    21. }
    22. ]
    23. }

    此时,请求在索引last_three_month中搜索uid为001的用户的入住记录,搜索的DSL如下:

    1. GET /last_three_month/_search
    2. {
    3. "query": {
    4. "term": {
    5. "uid": {
    6. "value": "001"
    7. }
    8. }
    9. }
    10. }

    运行结果如下:

    1. {
    2. "took" : 10,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 3,
    6. "successful" : 3,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : {
    12. "value" : 3,
    13. "relation" : "eq"
    14. },
    15. "max_score" : 0.2876821,
    16. "hits" : [
    17. {
    18. "_index" : "february_log",
    19. "_type" : "_doc",
    20. "_id" : "001",
    21. "_score" : 0.2876821,
    22. "_source" : {
    23. "uid" : "001",
    24. "hotel_id" : "23456",
    25. "createDate" : "2021-02-05"
    26. }
    27. },
    28. {
    29. "_index" : "january_log",
    30. "_type" : "_doc",
    31. "_id" : "001",
    32. "_score" : 0.2876821,
    33. "_source" : {
    34. "uid" : "001",
    35. "hotel_id" : "12345",
    36. "createDate" : "2021-01-05"
    37. }
    38. },
    39. {
    40. "_index" : "march_log",
    41. "_type" : "_doc",
    42. "_id" : "001",
    43. "_score" : 0.2876821,
    44. "_source" : {
    45. "uid" : "001",
    46. "hotel_id" : "34567",
    47. "createDate" : "2021-03-05"
    48. }
    49. }
    50. ]
    51. }
    52. }

            由上面的结果可知,当请求搜索last_three_month的数据时,ES将请求转发到了january_log、february_log和march_log3个索引中。

            在默认情况下,当一个别名只指向一个索引时,写入数据的请求可以指向这个别名,如果这个别名指向多个索引(就像上面的例子),则写入数据的请求是不可以指向这个别名的。例如,向last_three_month中写入一条数据:

    1. POST /last_three_month/_doc/002
    2. {
    3. "uid":"002",
    4. "hotel_id":"2222",
    5. "createDate":"2022-03-06"
    6. }

    ES返回报错信息如下:

    1. {
    2. "error" : {
    3. "root_cause" : [
    4. {
    5. "type" : "illegal_argument_exception",
    6. "reason" : "no write index is defined for alias [last_three_month]. The write index may be explicitly disabled using is_write_index=false or the alias points to multiple indices without one being designated as a write index"
    7. }
    8. ],
    9. "type" : "illegal_argument_exception",
    10. "reason" : "no write index is defined for alias [last_three_month]. The write index may be explicitly disabled using is_write_index=false or the alias points to multiple indices without one being designated as a write index"
    11. },
    12. "status" : 400
    13. }

            根据上面的报错信息可知,在默认情况下,ES不能确定向last_three_month写入数据时的转发对象。这种情况需要在别名设置时,将目标索引的is_write_index属性值设置为true来指定该索引可用于执行数据写入操作。例如设置january_log为数据写入转发对象,对应的DSL如下:

    1. POST /_aliases
    2. {
    3. "actions": [
    4. {
    5. "add": {
    6. "index": "january_log",
    7. "alias": "last_three_month",
    8. "is_write_index": true
    9. }
    10. }
    11. ]
    12. }

            此时可以再向last_three_month中写入上面的数据。将索引别名last_three_month的数据写入转发对象设置为索引january_log之后,再向last_three_month发起写入数据的请求时,ES会将该请求转发到索引january_log中。

            引入别名之后,还可以用别名表示索引之间的替代关系。这种关系一般是在某个索引被创建后,有些参数是不能更改的(如主分片的个数),但随着业务发展,索引中的数据增多,需要更改索引参数进行优化。我们需要平滑地解决该问题,既要更改索引的设置,又不能改变索引名称,这时就可以使用索引别名。

            比如一个旅馆的搜索别名设置为hotel,初期创建索引hotel_1时,主分片个数设置为5,然后设置hotel_1的别名为hotel。此时客户端使用索引别名hotel进行搜索请求,该请求会转发到索引hotel_1中。

            如果此时旅馆索引中的新增数据急剧增长,索引分片需要扩展,需要将其扩展成为10个分片的索引。但是一个索引在创建后,主分片个数已经不能更改,因此只能考虑使用索引替换来完成索引的扩展。这时可以创建一个索引hotel_2,除了将其主分片个数设置为10外,其他设置与hotel_1相同。当hotel_2的索引数据准备好后,删除hotel_1的别名hotel,同时,设置hotel_2的别名为hotel。此时客户端不用进行任何改动,继续使用hotel进行搜索请求时,该请求会转发给索引hotel_2。如果服务稳定,最后将hotel_1删除即可。此时借助别名就完成了一次索引替换工作。

            如下图,hotel索引别名暂时指向hotel_1,hotel_2做好了数据准备;在右图中,hotel索引别名指向hotel_2,完成了索引的扩展切换。

     案例演示

    首先建立索引hotel_1,设置其主分片个数为5,其他信息与创建索引时保持一致。

    1. PUT /hotel_1
    2. {
    3. "settings": {
    4. "number_of_shards": 5,
    5. "number_of_replicas": 2
    6. },
    7. "mappings": {
    8. "properties": {
    9. "title":{"type": "text"},
    10. "city":{"type": "keyword"},
    11. "price":{"type": "double"}
    12. }
    13. }
    14. }

    在数据写入端向hotel_1写入搜索数据,请求的DSL如下:

    1. POST /hotel_1/_doc/001
    2. {
    3. "title":"java旅馆",
    4. "city":"深圳",
    5. "price": 50.00
    6. }

    建立别名hotel,请求的DSL如下:

    1. POST /_aliases
    2. {
    3. "actions": [
    4. {
    5. "add": {
    6. "index": "hotel_1",
    7. "alias": "hotel"
    8. }
    9. }
    10. ]
    11. }

    假设过一段时间后旅馆索引的分片需要扩展。通过变更索引的方式可以完成扩展。建立索引hotel_2,并设置主分片个数为10,设置副分片个数为2,请求的DSL如下:

    1. PUT /hotel_2
    2. {
    3. "settings": {
    4. "number_of_shards": 10,
    5. "number_of_replicas": 2
    6. },
    7. "mappings": {
    8. "properties": {
    9. "title":{"type": "text"},
    10. "city":{"type": "keyword"},
    11. "price":{"type": "double"}
    12. }
    13. }
    14. }

    在数据写入端向索引hotel_2中写入搜索数据,请求的DSL如下:

    1. POST /hotel_2/_doc/001
    2. {
    3. "title":"java旅馆",
    4. "city":"深圳",
    5. "price": 50.00
    6. }

    此时hotel_2中的数据已经准备完毕,现在变更别名设置,删除hotel_1的索引别名,设置索引hotel_2的别名为hotel2,请求的DSL如下:

    1. POST /_aliases
    2. {
    3. "actions": [
    4. {
    5. "remove": { //删除索引hotel_1的别名hotel
    6. "index": "hotel_1",
    7. "alias": "hotel"
    8. }
    9. },
    10. {
    11. "add": { //增加索引hotel_2的别名hotel
    12. "index": "hotel_2",
    13. "alias": "hotel"
    14. }
    15. }
    16. ]
    17. }

            此时请求hotel索引进行搜索时,搜索已经从转发给hotel_1变更为转发给hotel_2。因此,索引别名在这种需要变更索引的情况下,搜索端不需要任何变更即可完成切换,这在实际的生产环境中是非常方便的。

  • 相关阅读:
    【ChatGLM2-6B】nginx转发配置
    python 多项式回归以及可视化
    STARK Low Degree Testing——FRI
    U盘RAW格式怎么恢复 U盘RAW格式怎么改过来
    2023年的深度学习入门指南(27) - CUDA的汇编语言PTX与SASS
    IDEA乱码问题解决
    第十五章 配置工作队列管理器类别
    【滤波估计】基于双卡尔曼滤波实现soc和soh联合估计附matlab代码
    数据库update、delete误操作,使用binlog2sql手动回退
    数据结构——图の选择题整理
  • 原文地址:https://blog.csdn.net/ntzzzsj/article/details/126119302