资讯详情

Go Elasticsearch index CRUD

文章目录

  • 1.简介
  • 2.增加
  • 2.删除
  • 3.修改
    • 3.1 更新 mapping
      • 3.1.1 增加字段
      • 3.1.2 删除字段
      • 3.1.3 添加 multi-fields
    • 3.2 重命名 index
  • 4.查询
  • 5.小结
  • 参考文献

1.简介

Elasticsearch 的索引(index)是文档(document)集合,类似 MySQL 手表。文档是 ES 一个存储在中间 JSON 格式数据。

index 逻辑空间的概念,index 中文档将分散在不同的地方 shard 中,而 shard 在 ES 它是物理空间的概念。

index 由以下部分组成:

  • data:由 document metadata 所组成;
  • mapping:用于定义文档结构,如字段名称 & 类型;
  • setting:如何存储定义数据,如 shard 和 replica 数量。

下面设计一个 index 描述我们想要存储的用户信息,index 也用一个 JSON 串来表示。

index = `{ "mappings":{ "dynamic": "strict", "properties":{ "id": { "type": "long" }, "username": { "type": "keyword" }, "nickname": { "type": "text" }, "phone": { "type": "keyword" }, "age": { "type": "long" }, "ancestral": { "type": "text" }, "identity": { "type": "text" }, "update_time": { "type": "long" }, "create_time": { "type": "long" } } }, "settings" : { "index" : { "number_of_shards" : "1", "number_of_replicas" : "1" } } }` 

其中 dynamic 是 mapping 一个非常重要的属性 ,控制是否动态添加新字段,并接受以下参数:

参数 说明
true New fields are added to the mapping (default).
runtime New fields are added to the mapping as runtime fields. These fields are not indexed, and are loaded from _source at query time.
false New fields are ignored. These fields will not be indexed or searchable, but will still appear in the _source field of returned hits. These fields will not be added to the mapping, and new fields must be added explicitly.
strict If new fields are detected, an exception is thrown and the document is rejected. New fields must be explicitly added to the mapping.
  • dynamic 为 true 表示动态映射(dynamic mapping)。

true 缺省值。如果添加的文档中有新的字段,则 ES 在映射中自动添加新的字段。可以索引新的字段,即可以搜索,mapping 同时也更新。

  • dynamic 为 false 表示静态(显式)映射(explicit mapping)。

当 ES 当发现有新字段时,会写入新字段,但不会索引新字段,即不能通过新字段查询。在某些情况下,静态映射仍然不够,因此需要更严格的策略来进一步限制。

  • dynamic 为 strict 表示精确(严格)映射(strict mapping)。

字段需要严格匹配,新字段写入会报错。

一般静态映射使用较多。 HTML 的 img 标签一样,src 您可以在需要时添加自己的属性 id 或者 class 属性。当然,如果你非常了解你的数据,并且在未来很长一段时间内不会改变,strict 这是个不错的选择。

动态映射很方便,但是实际业务中,对于关键字段类型,通常预先定义好,这样可以避免 ES 自动生成不是你想要的字段类型。

2.增加

设计好了 index 及 mapping 之后,我们开始编写代码创建。

// ESIndexExists 索引是否存在。 func ESIndexExists(ctx context.Context, index string) (bool, error) { 
          return GetESClient().IndexExists(index).Do(ctx) }  // CrtESIndex 创建 ES 索引。 func CrtESIndex(ctx context.Context, index,string) error { 
        
	exist, err := ESIndexExists(ctx, index)
	if err != nil { 
        
		return err
	}
	// 已经创建
	if exist { 
        
		return nil
	}
	// 重复创建会报错
	_, err = GetESClient().CreateIndex(index).BodyString(desc).Do(ctx)
	return err
}

因为重复创建 index,ES 会报错,所以创建前先判断一下是否已经创建。

创建成功后,我们在 Kibana 上通过 Restful API 可以查看到刚刚创建的 index。

GET /es_index_userinfo

{ 
        
  "es_index_userinfo" : { 
        
    "aliases" : { 
         },
    "mappings" : { 
        
      "dynamic" : "strict",
      "properties" : { 
        
        "age" : { 
        
          "type" : "long"
        },
        "ancestral" : { 
        
          "type" : "text"
        },
        "create_time" : { 
        
          "type" : "long"
        },
        "id" : { 
        
          "type" : "long"
        },
        "nickname" : { 
        
          "type" : "text"
        },
        "phone" : { 
        
          "type" : "keyword"
        },
        "update_time" : { 
        
          "type" : "long"
        },
        "username" : { 
        
          "type" : "keyword"
        }
      }
    },
    "settings" : { 
        
      "index" : { 
        
        "creation_date" : "1627546052453",
        "number_of_shards" : "1",
        "number_of_replicas" : "1",
        "uuid" : "_FIlQz-uQD2ynzITVPFpRw",
        "version" : { 
        
          "created" : "7070099"
        },
        "provided_name" : "es_index_userinfo"
      }
    }
  }
}

对应的 RESTful API 为:

PUT /es_index_userinfo
{ 
        
  "mappings":{ 
        
		"dynamic": "strict",
		"properties":{ 
        
			"id": 				{ 
         "type": "long" },
			"username": 		{ 
         "type": "keyword" },
			"nickname":			{ 
         "type": "text" },
			"phone":			{ 
         "type": "keyword" },
			"age":				{ 
         "type": "long" },
			"ancestral":		{ 
         "type": "text" },
			"update_time":		{ 
         "type": "long" },
			"create_time":		{ 
         "type": "long" }
		}
	}
}

2.删除

通过 RESTful API 删除 index 很简单,格式如下:

DELETE /<index>

比如删除上面创建的 es_index_userinfo。

DELETE /es_index_userinfo

3.修改

对于一个已经存在的 index,我们可以修改 index 的相关设置。

3.1 更新 mapping

3.1.1 增加字段

比如修改文档结构,即修改 index 的 mapping,我们想其中再增加一个字段爱好 hobby。

PUT /es_index_userinfo/_mapping
{ 
        
  "properties": { 
        
    "hobby": { 
        
      "type":"text"
    }
  }
}

3.1.2 删除字段

ES 中已经添加成功的字段是没法直接删除的,因为这会导致数据不可用。我们可以通过间接的方式来完成字段的删除。操作步骤如下: (1)创建一个新的 index,不包含要删除的字段; (2)删除原 index 中待删除字段的数据。只删除数据,不删除字段。因为如果不清空字段值的话,在下面的 reindex 会出现问题,如果新 index 的 mapping 的 dynamic 属性为 strict,会出错。

POST es_index_userinfo/_update_by_query
{ 
        
    "script" : "ctx._source.remove('hobby')",
    "query": { 
        
        "match_all": { 
        }
    }
}

(3)通过 redindex 将数据拷贝至新的 index;

POST /_reindex
{ 
        
  "source": { 
        
    "index": "my-index"
  },
  "dest": { 
        
    "index": "my-new-index"
  }
}

(4)删除旧的 index; (5)给新 index 添加别名,别名是旧 index。

POST <target>/_alias/<alias>

注意:完成第四步后,才能进行第五步的操作,期间会导致依赖该 index 的服务短暂不可用,所以尽量在业务低峰时间段操作。最安全的做法,是完成上面前三部操作后,将服务通过配置的方式把使用的 index 切换到新的 index。再进行后面的两步操作。

3.1.3 添加 multi-fields

一个字段可以存在多个类型,通过添加 multi-fields 来实现。

比如一个字段既要支持分词匹配,又要支持全词匹配,那么需要为其添加两个类型,分别是 text 和 keyword。

PUT /<index>/_mapping
{ 
        
  "properties": { 
        
    "city": { 
        
      "type": "text",
      "fields": { 
        
        "raw": { 
        
          "type": "keyword"
        }
      }
    }
  }
}

引用 keyword 的类型字段方式为city.raw

这里需要注意的是,新增的字段 raw 只对新加入的 document 生效,旧的数据无法通过新字段 raw 来检索。如果想要对旧数据生效,一般有两个做法: (1)更新旧字段。读取旧字段的值重新覆盖一次。

POST /<index>/_update_by_query?refresh=true
{ 
        
  "query": { 
        
    "match_all":{ 
        }
  },
  "script": { 
        
    "source": "ctx._source['city'] = ctx._source.city"
  }
}

(2)reindex。新建一个 index,将旧 index 数据拷贝到新的 index,再删除旧 index,再给新 index 添加一个别名为旧 index。

3.2 重命名 index

ES 中不能直接重命名 index,因为这会造成旧 index 不可用。我们可以给 index 添加别名,达到重命名的效果。

POST <target>/_alias/<alias>

4.查询

查询一个 index 也很简单,接口调用格式如下:

GET /<index>

5.小结

本文只是简单的介绍了 index 的概念,组成和相关操作,关于 index 和 mapping 的更多操作,请参考官方文档 Elasticsearch Guide [8.0] » REST APIs » Index APIs。


参考文献

Elasticsearch Guide [8.0] » REST APIs » Index APIs Elasticsearch Guide [8.1] » REST APIs » Index APIs » Update mapping API Elasticsearch Guide [8.1] » Mapping » Mapping parameters » dynamic 简书.es删除字段

标签: uqd侧装智能大浮球液位变送器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台