部分字段查询和更新
Pb对象是嵌套树结构,完整的Pb message可能会较大,tcaplus可支持对部分字段或嵌套字段的查询和更新,如"timekey", "pay.order.desc", "str_map['key'].desc"。
示例表:
message tb_online3 {
option(tcaplusservice.tcaplus_primary_key) = "openid";
message order_info {
int32 oid = 1;
string desc = 2;
}
message pay_info {
double total_money = 1;
uint64 pay_times = 2;
order_info order = 3;
int32 pid = 4;
string desc = 5;
}
int32 openid = 1;
uint32 tconndid = 2;
string timekey = 3;
repeated int64 lockid = 4;
pay_info pay = 5;
repeated pay_info pay_array = 6;
repeated string desc_array = 7;
map<int32, all_type_t> int_map = 9;
map<string, all_type_t> str_map = 10;
map<string, string> str_str = 11;
}
部分字段查询
Pb表支持部分字段更新,见FieldGet接口,大致参数如下:
- 入参&出参:pb message,message中的key,作为输入;查询成功之后,返回的数据会回填到这个message中作为输出。
- 入参:field_paths,指定的要更新的字段集合,如{"timekey", "pay.order.desc", "str_map['key'].desc"}。
- 入参:condition,条件过滤,仅当条件满足时才返回,否则会返回条件不匹配的错误码
COMMON_ERR_CONDITION_NOT_MATCHED。
支持以下类型的字段:
- 一级字段,如"timekey"、"pay"、"desc_array"。
- 嵌套字段,如"pay.order.desc"。
- Map的元素的嵌套字段,如"int_map[1001]"、"str_str['key'],对于"str_map['key'].desc",若map的key不存在则报错
COMMON_ERR_ELEMENT_NOT_EXIST。 - 数组的嵌套字段,如"pay_array[0]"、"pay_array[0].order.desc",若数组下标不存在则报错。
- 数组范围,如"pay_array[0-100]"、"pay_array[0- -1]",其中-1表示直到末尾。
- 一趟请求,可支持对多个字段进行查询,如{"timekey", "pay.order.desc", "str_map['key'].desc"}。
- 但是多字段不能有路径重叠,如{"pay", "pay.order.desc"},可能得不到预期结果。
字段路径的总结,使用点号(.)表示嵌套字段,使用方括号([])表示数组索引和map key,不支持路径中使用多个方括号([]),如"map['key'].a.sub_map['sub_key']"。
部分字段更新
Pb表支持部分字段更新,见C++ SDK的FieldSet接口,Go SDK的FieldUpdate接口。
FieldSet或FieldUpdate的行为如下:
- 入参&出参:pb message,message中的key和包含的增量数据,作为输入;更新成功之后,返回的数据会回填到这个message中。
- 入参:field_paths,指定的要更新的字段集合,如{"timekey", "pay.order.desc", "str_map['key'].desc"}。
- 入参:operation,额外捎带的文本描述的操作,如"pay.pay_times += 1"。
- 入参:condition,条件过滤,仅当条件满足时才更新,否则会返回条件不匹配的错误码
COMMON_ERR_CONDITION_NOT_MATCHED。
部分字段更新,支持以下这些类型的字段:
- 一级字段的更新,如"timekey"、"pay"、"desc_array"。
- 嵌套字段,如"pay.order.desc"。
- Map的元素的嵌套字段,如"int_map[1001]"、"str_map['key'].desc"、"str_str['key'],若map的key不存在则创建之。
- Map元素的插入,如"PUSH int_map[1001]",若map的key已存在则报错。
- Map元素的删除,如"POP int_map[1001]",若map的key不存在,也会返回成功。
- 一趟请求,可支持对多个字段进行更新,会同时生效,如{"timekey", "pay.order.desc", "str_map['key'].desc"}。
- 但是多字段更新不能有路径重叠,如{"pay", "pay.order.desc"},不会报错,但因为更新顺序问题可能得不到预期结果。
因为对Map元素的更新,可以支持一种类Schema-free的用法,见《Schema-free》。
不支持像map元素一样,对数组元素的更新(即repeated字段):
- 不支持数组元素的嵌套字段,如"pay_array[0]"、"pay_array[0].desc",只支持数组字段的整体更新(即"pay_array")。
- 若要更新数组,只能通过operation语句对数组元素进行PUSH、SET、POP操作,文本语法见《条件过滤和更新语法说明》,能力与限制见《条件过滤和更新功能》。
字段路径的总结,使用点号(.)表示嵌套字段,使用方括号([])表示map key(不支持数组索引),不支持路径中使用多个方括号([]),如"map['key'].a.sub_map['sub_key']"。
记录不存在时创建
默认,当修改的记录不存在时,会报错TXHDB_ERR_RECORD_NOT_EXIST。
若希望记录不存在时,自动创建,可通过接口SetMessageOption设置。
C++SDK相关接口:
/**
* i).MESSAGE_OPTION_ENABLE_SET_NOT_EXIST = 9, API中设置允许FieldSet操作不存在的记录时创建之,取值0不允许,取值1允许
*/
int SetMessageOption(const ::google::protobuf::Message &msg, int32_t item, const std::string &option);
GoSDK相关接口:
const (
TcaplusFlagInsertRecordIfNotExist int32 = 16 //PB的FieldUpdate使用,数据不存在则插入
)
func (req *pbFieldUpdateRequest) SetFlags(flag int32) int
ResultFlag
更新返回之后,默认总是把请求的key和增量数据回填到原message(入参&出参)。
而有些场景下,需要返回其他数据,如更新前的旧数据,接口SetMessageOption支持设置返回数据。
C++SDK相关接口:
/**
* j).MESSAGE_OPTION_RESULT_FLAG_FOR_SUCCESS = 10, 用户显式设置请求执行成功时的响应标志,会覆盖API的默认配置
* option取值有 "0":表示只需返回操作执行成功与否
* "1":表示返回与请求字段一致
* "2":表示须返回变更记录的所有字段最新数据
* "3":表示须返回变更记录的所有字段旧数据
* 其中,对于FieldSet操作,不设置该选项,总是返回和请求一致的数据
* k).MESSAGE_OPTION_RESULT_FLAG_FOR_FAIL = 11, 用户显式设置请求执行失败时的响应标志,会覆盖API的默认配置
* option取值有 "0":表示只需返回操作执行成功与否
* "1":表示返回与请求字段一致
* "2":表示须返回变更记录的所有字段最新数据
* "3":表示须返回变更记录的所有字段旧数据
* 其中,对于FieldSet操作,不设置该选项,总是返回和请求一致的数据
*/
int SetMessageOption(const ::google::protobuf::Message &msg, int32_t item, const std::string &option);
GoSDK相关接口:
const (
TcaplusResultFlagNoValue byte = 0
TcaplusResultFlagSameWithRequest byte = 1
TcaplusResultFlagAllNewValue byte = 2
TcaplusResultFlagAllOldValue byte = 3
)
func (req *pbFieldUpdateRequest) SetResultFlagForSuccess(result_flag byte) int
func (req *pbFieldUpdateRequest) SetResultFlagForFail(result_flag byte) int
当option取值2、3时,返回的是记录的所有字段数据(非部分修改字段),若完整记录数据较大时,高频操作会占用较大的网路带宽。