TcaplusDB知識庫 條件過濾說明與更新

2022-09-09 20:30:26 字數 4019 閱讀 7354

針對更靈活的資料訪問操作,tcaplusdb 支援條件操作的能力,具備以下能力:

generic 表和 list 表都支援條件操作。

這裡分別定義兩種型別的表,用於本章節示例,為了更直觀說明條件過濾和更新。本章節以protobuf協議作為示例,但tdr協議同樣支援條件過濾和更新,使用類似。

syntax = "proto3";

package mytcaplustable;

import "tcaplusservice.optionv1.proto";

​message user

​int32 id = 1;

string name = 2;

int32 rank = 3;

repeated int64 gameids = 4;

repeated mail mailbox = 5;

}

syntax = "proto3";

package mytcaplustable;

import "tcaplusservice.optionv1.proto";

​message list_user

​int32 id = 1;

string name = 2;

int32 rank = 3;

repeated int64 gameids = 4;

repeated mail mailbox = 5;

}

支援記錄級別的條件過濾,只有滿足條件,才對指定的(乙個或多個)記錄進行操作,包括對記錄修改、刪除或查詢等。

若沒有條件過濾,對於 generic 表,通過主鍵查詢或操作乙個記錄,若對應主鍵不存在,則返回錯誤碼 txhdb_err_record_not_exist。

而條件則在這基礎上再加一層過濾,對於 generic 表,主鍵 key 對應存在基礎上,必須條件滿足才能查詢或操作對應的記錄,否則返回錯誤碼 common_err_condition_not_matched。

key + condition,相當於 sql 中的where語句,雖然能力比 sql 還差不少,但已經提供一定程度的靈活能力。 特別是對於「讀判斷-然後寫」的原子操作場景特別有用,條件更新的初衷就是解決這個問題的。

例如,對於 user 表,若 gameids 陣列不包含 101 這個元素,那麼在該陣列插入 101,那麼應用**會寫成如下

user u;

// 設定主鍵

u.set_id(1);

u.set_name("a");

int ret = api.get(&u);

// ...

if (!find(u.gameids(), 101)) // find是應用實現的函式,在陣列中找是否存在某元素

上述**存在幾個問題

針對上述問題,條件更新可以解決一些互動多、非原子等問題,示例條件操作**如下:

user u;

// 設定主鍵

u.set_id(1);

u.set_name("a");

// 先判斷gameids是否已經包含101,若不存在(條件不滿足)再插入101

int ret = api.updateitem(&u, "push gameids#[-1][$ = 101]", "gameids not contains($==101)");

if (ret == common_err_condition_not_matched) // 條件不滿足,說明gameids已經存在101了

上述**,"gameids not contains($==101)"就是過濾條件,而"push gameids#[-1][$ = 101]"是陣列操作語句,後文介紹,這裡指在 gameids 陣列尾部插入 101。

tcaplusdb 提供的一些 protobuf api 新增了const std::string &condition入參,用於指定過濾條件,支援 condition 的介面以及新增的錯誤碼詳見後文的附錄。

一些介面的使用示例如下,更多的示例可見詳細 example。

// tcaplus_coroutine_pb_api.h

int set(::google::protobuf::message *msg, const std::string &operation = "", const std::string &condition = "");

​int fieldinc(const std::set<:string> &dottedpaths, ::google::protobuf::message *msg, const std::string &operation = "", const std::string &condition = "");

​int tr**erse(::google::protobuf::message *msg, const std::string &condition, tcaplustr**ersecallback *cb);

​// example.cpp

user u;

// 設定主鍵

u.set_id(1);

u.set_name("a");

// 設定其他內容

// ...

// 當rank>100,才執行set操作,若條件不滿足會返回對應的錯誤碼

int ret = api.set(&u, "", "rank > 100");

if (ret == common_err_condition_not_matched) // 條件不滿足的情況

​// 設定遞增的步長

u.set_rank(1);

// 當rank達到上限100之後,不在對rank遞增,否則 +1

std::set<:string> dottedpaths;

dottedpaths.insert("rank");

ret = api.fieldinc(dottedpaths, &u, "", "rank < 100");

​// 遍歷2021-01-01年之後修改過的記錄,這裡$.lastaccesstime是記錄的內建屬性,表示記錄的最後更新時間

int ret = api.tr**erse(&u, "$.lastaccesstime >= \"2021-01-01\"", &tr**ersecallback);

過濾條件是類 sql 的 where 語句的語法,已支援以下幾種過濾能力

完整語法如下

condition_expr ::=

array contains '(' condition ')'

| array not contains '(' condition ')'

| condition

​condition ::=

operand

| operand comparator operand

| condition and condition

| condition or condition

| not condition

| operand bitwise_op operand

​comparator ::=

==| =

| <

| >

| <=

| >=

| !=

​bitwise_op ::=&​

array ::=

identifier

​operand ::=

identifier

| number

| string

| $| $.lastaccesstime

比較操作符優先順序條件過濾的效能和 1)條件表示式、2)表的模式 有關,滿足以下規則時,有針對性的效能優化(僅供參考,內部實現可能會調整):

TcaplusDB知識庫 PB表定義示例

以下是protobuf表game players.proto的示例,您可以將檔案上傳到控制台並建立該錶。syntax proto3 指定protobuf語言版本,proto3.匯入tcaplusdb公共定義服務 import tcaplusservice.optionv1.proto message...

TcaplusDB知識庫 TDR表資料型別有哪些

目前對於c c c 語言,支援的基本資料型別如下表所示 型別名分類 儲存長度 位元組 取值範圍 byte位元組1 char 單位元組字元 1tinyint整數1 128 127 tinyuint整數1 0 255 smallint整數2 32768 32767 smalluint整數2 0 6553...

打造「個人知識庫」

在以前舉辦的巡迴講座時有許多讀得就問到同乙個問題,就是如何有效記往這些平常在工作摸索或者從書中,或與交流中得到的經驗與方法。說經常在工作遇到某些問題似曾相識,卻想不起以前的解決方法了,很是苦惱。其實這是每個人都會遇到的,不是個人問題。特別是對於我們網管這個行業,所涉及的知識面非常廣,可以說沒有人能把...