Elasticsearch 数据处理:upsert
Elasticsearch 插入数据,中间由于网络等问题,有可能会使数据重复上报,就需要执行upsert(存在就更新,不存在就插入)的操作。
type AppFlow struct {
OpTime int64 `json:"opTime"` // 操作时间
UserId string `json:"userId"` // 用户id
App string `json:"app"` // app
Flow int64 `json:"flow"` // 流量
Channel string `json:"channel"` // 渠道
}
eg:在上面结构中需要实现upsert就需要设置一个类似于mysql 的唯一索引,检查重复。Elasticsearch 中又没有设置唯一索引的操作。所以在往Elasticsearch 插入数据的时候,需要加一个_id字段做唯一索引
func (e *AppFlow) GetId() string {
return fmt.Sprintf("%d_%s_%s_%s", e.OpTime, e.UserId, e.App, e.Channel)
}
在插入数据的时候指定id,Elasticsearch 就会根据id执行upsert操作
func (e *AppFlow) EsAddBulk(ctx context.Context, data []*AppFlow) error {
idx := "index_name"
bulkRequest := getESClient().Bulk()
for _, v := range data {
tmp := v
req := elastic.NewBulkIndexRequest().Index(idx).Id(v.GetId()).Doc(tmp)
bulkRequest = bulkRequest.Add(req)
}
bulkResponse, err := bulkRequest.Do(ctx)
if err != nil {
log.print("Error app flow bulk insert: %s", err)
return err
}
// 检查批量响应的错误
if bulkResponse.Errors {
for _, item := range bulkResponse.Items {
for action, result := range item {
if result.Error != nil {
log.print("Failed to %s document: %s", action, result.Error.Reason)
}
}
}
}
return err
}