【TcaplusDB知识库】如何对数组进行操作

为了支持对数组的灵活操作,即 protobuf 中 repeated 字段,类似 Redis 中对 list、set 等数据结构的操作能力,TcaplusDB 提供对数组的命令式的操作。具备如下能力:

  • PUSH 操作:在数组指定位置插入新的元素数据。
  • SET 操作:修改数组指定位置的元素数据。
  • POP 操作:删除数组中某些下标范围或者满足某些条件的元素。
  • GET 查询:指定记录的 key,查询数组返回数组中某些下标范围或者满足某些条件的元素(即仅记录的局部数据)。

4.1 接口介绍

支持的PUSH、SET、POP操作 使用 UpdateItem 接口,支持的Get使用 Query 接口,其中 generic 表的 coroutine 接口定义如下:

// 入参/出参 msg:包含用户输入的key值,返回修改后的数据也填入到msg
// 入参 operation:数组操作语句,即PUSH、SET、POP
// 入参 condition:记录的过滤条件
int UpdateItem(::google::protobuf::Message *msg, const std::string &operation, const std::string &condition = "");

// 入参/出参 msg:包含用户输入的key值,返回查询的局部数据也填入到msg,注意,返回的msg会和输入的msg合并,相当于接口内部调用Message::MergeFrom
// 入参 operation:数组查询语句,即GET
// 入参 queryOption:查询选项,当前仅支持通过TCAPLUS_PB_API_QUERY_RETURN_ARRAY_INDEX指定是否需要返回查询数组元素的原始下标
// 入参 condition:记录的过滤条件
// 出参 vecArrayIndex:若指定TCAPLUS_PB_API_QUERY_RETURN_ARRAY_INDEX,返回查询数组元素的原始下标
int Query(::google::protobuf::Message *msg, const std::string &query, int queryOption, const std::string &condition, std::vector<int> &vecArrayIndex);

4.2 使用示例

这里列举几个使用示例,数组操作的详细语法见下一小节,更多示例见 example。

4.2.1 数组更新示例

user u;
// 设置主键
u.set_id(1);
u.set_name("a");

// 在mailbox数组尾部插入一个元素(同时对元素内的title等字段赋值),这里-1表示尾部的数组下标
int ret = api.UpdateItem(&u, "PUSH mailbox #[-1] [title = \"tcaplus\", content = \"...\"]");

// 当gameids数组不包含101时,在gameids数组头部插入一个元素101,这里0表示头部的数组下标,$表示当前操作的数组元素
// 注意,这里还多了第三个参数,即条件过滤,仅当条件满足时,才执行push操作
ret = api.UpdateItem(&u, "PUSH gameids #[0] [$ = 101]", "gameids NOT CONTAINS($ == 101)");

// 删除mailbox数组下标0 ~ 10范围内,且title不等于"tcaplus"的元素
ret = api.UpdateItem(&u, "POP mailbox #[0-10] [title != \"tcaplus\"]");

// 修改指定下标为1的元素
ret = api.UpdateItem(&u, "SET gameids #[1] [$ = 101]");

4.2.2 数组查询示例

user u;
// 设置主键
u.set_id(1);
u.set_name("a");

// 假设服务端user.mailbox包含4个元素,为
// [ { "tcaplus", "..." }, { "not-tcaplus", "..." }, { "tcaplus", "..." }, { "not-tcaplus", "..." } ]

// 查询mailbox数组下标为0 ~ 2且title为"tcaplus"的元素
// 这里仅返回局部数据,即两个数组元素,并填入u中,也就是说u既作为入参(提供主键),也是出参(包含返回的局部数据)
// option设置TCAPLUS_PB_API_QUERY_RETURN_ARRAY_INDEX时,则也会返回这两个元素的下标,即0和2
int option = 0;
option |= TCAPLUS_PB_API_QUERY_RETURN_ARRAY_INDEX;
std::vector<int> vecArrayIndex;
ASSERT_EQ(0, u.mailbox_size());
int ret = api.Query(&u, "GET mailbox #[0-2] [title == \"tcaplus\"]", option, "", vecArrayIndex);
if (ret == 0) {
    ASSERT_EQ(2, u.mailbox_size());
    ASSERT_EQ(0, vecArrayIndex[0]);
    ASSERT_EQ(2, vecArrayIndex[1]);
}

4.3 语法说明

PUSH 和 SET 语法一样,只有语义上的差异,前者在指定位置插入,后者在指定位置原地修改。

PUSH 和 SET 语法由 3 部分组成,即 数组字段名称 + 下标 + 若干个赋值表达式。其中当元素是组合类型,是各个字段的赋值,当元素是基本类型,使用$引用当前元素进行赋值。

POP 的语法由 3 部分组成,即 数组字段名称 + 下标范围 + 嵌套的过滤条件,后两个是可选的。 和 PUSH 不同,POP 可以某些下标范围而不仅仅是单个下标,这里过滤条件的语法和上一章节记录的过滤条件一样,区别是过来条件的上下文不一样,这里的是元素的数据,而另一个是整个记录的数据。

GET 的语法和 POP 一样。

完整的操作语法如下

push_expr ::=
    PUSH array # '[' index ']' '[' assign_expr [, assign_expr]* ']'

set_expr ::=
    SET array # '[' index ']' '[' assign_expr[, assign_expr]* ']'

pop_expr ::=
      POP array
    | POP array # '[' index_range ']'
    | POP array # '[' index_range ']' '[' condition ']'

get_expr ::=
      GET array
    | GET array # '[' index_range ']'
    | GET array # '[' index_range ']' '[' condition ']'

assign_expr ::=
      identifier = number | string
    | $ = number | string

index ::=
    integer

index_range ::=
      index [, index_range]*
    | index - index [, index_range]*
  • 语法说明

  • assign_expr: 赋值表达式,若数组元素是组合类型,则是内部字段的赋值title = \"tcaplus\", content = \"...\",若元素是基本类型,则使用$引用元素本身,如$=101

  • index: 数组的下标,其中 0 表示数组头部下标,在不知道数组大小情况下,使用-1 表示尾部的下标。

  • index_range: 数组下标范围,如 “0 - -1” 表示所有的下标,也可以表示多个不连续的范围,如 “0 - 8, -1”。

  • condition: 嵌套的过滤条件,语法和上一章节记录的条件过滤一致,区别在于,前者的语义上下文是整个记录的数据,这里的是数组元素中的数据。

  • PUSH/SET 的说明

  • 赋值表达式中,当前只支持对整型、浮点、字符串类型的字段赋值,且必须非 repeated 类型,若 repeated 字段本身是基本类型,则使用$引用的元素自身。

  • 赋值表达式中,不同类型整型、浮点型可以相互赋值,即会进行类型强转,有可能出现截断等情况,类型转换的行为和 C++中一致。

  • 对于 SET,若数组大小为 N,下标的有效范围是 0 ~ (N - 1)或-1。

  • 对于 PUSH,若数组大小为 N,下标的有效范围是 0 ~ N 或-1。

  • POP 的说明

  • POP,删除某些范围或某些满足条件的元素。

  • 基于 删除不存在的元素不会报错 的原则,pop 指定一个不存在的下标范围时,不会报错,例如数组大小为 10,8-80会删除最后 2 个元素。


img

TcaplusDB是腾讯出品的分布式NoSQL数据库,存储和调度的代码完全自研。具备缓存+落地融合架构、PB级存储、毫秒级时延、无损水平扩展和复杂数据结构等特性。同时具备丰富的生态、便捷的迁移、极低的运维成本和五个九高可用等特点。客户覆盖游戏、互联网、政务、金融、制造和物联网等领域。

猜你喜欢

转载自blog.csdn.net/weixin_44545651/article/details/121476077