func convertUpdate(rule *config.Rule, rows [][]interface{}) ([]elastic.BulkableRequest, error) {
	if len(rows)%2 != 0 {
		return nil, errors.Errorf("invalid update rows event, must have 2x rows, but %d", len(rows))
	}

	reqs := make([]elastic.BulkableRequest, 0, len(rows))
	var err error = nil

	for i := 0; i < len(rows); i += 2 {
		beforeID, err := rule.DocId(rows[i])
		if err != nil {
			log.Warnf("skipping row update due to problem with before update values: %v\n", err)
			continue
		}

		afterID, err := rule.DocId(rows[i+1])
		if err != nil {
			log.Warnf("skipping row update due to problem with update values: %v\n", err)
			continue
		}

		beforeParentID, afterParentID := "", ""
		beforeParentID, err = rule.ParentId(rows[i])
		if err != nil {
			return nil, errors.Trace(err)
		}
		afterParentID, err = rule.ParentId(rows[i+1])
		if err != nil {
			return nil, errors.Trace(err)
		}

		var req elastic.BulkableRequest
		req = elastic.NewBulkUpdateRequest().Index(rule.Index).Type(rule.Type).Parent(beforeParentID).Id(beforeID).Routing(beforeParentID)

		if beforeID != afterID || beforeParentID != afterParentID {
			// if an id is changing, delete the old document and insert a new one
			req = elastic.NewBulkDeleteRequest().Index(rule.Index).Type(rule.Type).Id(beforeID).Routing(beforeParentID)
			reqs = append(reqs, req)
			temp, err := convertInsert(rule, [][]interface{}{rows[i+1]})
			if err == nil {
				req = temp[0]
			}
		} else {
			doc := convertUpdateRow(rule, rows[i], rows[i+1])
			req = elastic.NewBulkUpdateRequest().Index(rule.Index).Type(rule.Type).Parent(beforeParentID).Id(beforeID).Routing(beforeParentID).Doc(doc)
		}
		reqs = append(reqs, req)
	}

	return reqs, err
}
// for insert and delete
func convertAction(rule *config.Rule, action string, rows [][]interface{}) ([]elastic.BulkableRequest, error) {
	reqs := make([]elastic.BulkableRequest, 0, len(rows))

	for _, values := range rows {
		if id, err := rule.DocId(values); err != nil {
			log.Warnf("skipping row %s due to: %v\n", action, err)
			continue
		} else {
			var req elastic.BulkableRequest

			if parentId, err := rule.ParentId(values); err != nil {
				return nil, err
			} else if action == canal.DeleteAction {
				req = elastic.NewBulkDeleteRequest().Index(rule.Index).Type(rule.Type).Id(id).Routing(parentId)
			} else {
				doc := convertRow(rule, values)
				req = elastic.NewBulkIndexRequest().Index(rule.Index).Type(rule.Type).Id(id).Parent(parentId).Doc(doc)
			}
			reqs = append(reqs, req)
		}
	}

	return reqs, nil
}