Schema Free of TcaplusDB
1. Application Scenarios
TcaplusDB supports multi-level nested table structure definitions. However, compared with document databases such as MongoDB, users still need to provide the Schema definition of the table.
Although TcaplusDB is not as flexible as MongoDB in this respect, TcaplusDB supports the use of Protobuf to define table structures, and can use the map type in Protobuf to support some degree of document data model usage with weak schemas.
2. Limitations on Use
Currently, only PB Tables support the use of weak schema.
3. Version Requirements
The TcaplusDB server version should be > = 3.55.0.
3. Instructions
2.1. PB Table Definitions
For example, for a table that stores user information, the traditional table definition might be as follows:
CREATE TABLE user (id int, name varchar(32), mailbox text, phone varchar(32), gameid int, ...);
Considering that the information structures of different records of the user are quite different, or that the user table structure may frequently add or delete fields, it is more appropriate to use such a table definition. The rest of the information of the user record is kept in a separate info field (json type):
CREATE TABLE user (id int, name varchar(32), info json);
Accordingly, a table structure can be defined in TcaplusDB as follows:
syntax = "proto3";
import "tcaplusservice.optionv1.proto";
message user {
option(tcaplusservice.tcaplus_primary_key) = "id";
int32 id = 1;
string name = 2;
map<string, string> info = 3;
}
Constraints & Descriptions
The upper limit of a single record cannot exceed 10MB
The value of the map type field can be any type of protobuf, such as message, to nest
When using API FieldSet/FieldGet to operate the map structure, the key of the map must be a string or integer
When using API FieldSet/FieldGet to operate the map structure, the value of the map can be a nested message, such as
info["sub_message"].field
, but currently it does not support nested arrays or nested maps, such asinfo["sub_map"]["sub_key"]
orinfo["sub_message"].sub_map["sub_key"]
There are some limitations to the map use of TcaplusDB. It cannot be nested as freely as json. The key and value of the map must be given a type when defining the table. Consider using
map<string, bytes>
for non-uniform value types
2.2. PB Table C++ SDK Examples
2.2.1 Inserting records
The value of the newly inserted record
{
"id": 1,
"name": "user_001",
"phone": "123456789",
"gameid": "1001",
"update_time": "2021-01-01 00:00:00"
}
API call
user u; // The user type is the precompiled type of the proto file
// Set primary key
u.set_id(1);
u.set_name("user_001");
// Set other information about the user
(*u.mutable_info())["phone"] = "123456789";
(*u.mutable_info())["gameid"] = "0";
(*u.mutable_info())["update_time"] = "2021-01-01 00:00:00";
api.Set(&u);
2.2.2 Adding & modifying fields
user u; // The user type is the precompiled type of the proto file
// Set primary key
u.set_id(1);
// Set the new value of the field to be updated
(*u.mutable_info())["update_time"] = "2021-07-01 00:00:00";
(*u.mutable_info())["gameid"] = "1002";
// Add the field 'mail' without changing the table structure
(*u.mutable_info())["mail"] = "user_001@xxx.com";
// Set the path to update the field
set<string> paths;
// SET operation, overwriting the value of info ['update_time']. If the value does not exist, create it
paths.insert("SET info['update_time']");
// PUSH operation. If the value does not exist, create it. If it already exists, report an error
paths.insert("PUSH info['gameid']");
// This is equivalent to SET info['mail']
paths.insert("info['mail']");
// Execute the modification, which is the original sub-operation
api.FieldSet(paths, &u, "", condition);
2.2.3 Deleting & modifying fields
user u; // The user type is the precompiled type of the proto file
// Set primary key
u.set_id(1);
// Set the new value of the field to be updated
(*u.mutable_info())["update_time"] = "2021-07-01 00:00:00";
// Set the path to modify the field
set<string> paths;
// Delete the gameid field and refresh the update_time
paths.insert("info['update_time']");
paths.insert("POP info['gameid']");
// Execute the modification, which is the original sub-operation
api.FieldSet(paths, &u);
2.2.4 Querying fields
user u; // The user type is the precompiled type of the proto file
// Set primary key
u.set_id(1);
// Set the path to get the field
set<string> paths;
paths.insert("name");
paths.insert("info['update_time']");
// Fill the FieldGet query result in u
api.FieldGet(paths, &u);
2.3. PB Table Go SDK Examples
2.3.1 Inserting records
The value of the newly inserted record
{
"id": 1,
"name": "user_001",
"phone": "123456789",
"gameid": "1001",
"update_time": "2021-01-01 00:00:00"
}
API call
user u; // The user type is the precompiled type of the proto file
// Set primary key
u.id = 1;
u.name = "user_001" ;
// Set other information about the user
u.info["phone"] = "123456789";
u.info["gameid"] = "0";
u.info["update_time"] = "2021-01-01 00:00:00";
api.Set(&u);
2.3.2 Adding & modifying fields
user u; // The user type is the precompiled type of the proto file
// Set primary key
u.id = 1;
// Set the new value of the field to be updated
u.info["gameid"] = "1002";
u.info["update_time"] = "2021-07-01 00:00:00";
// Add the field 'mail' without changing the table structure
u.info["mail"] = "user_001@xxx.com";
// Set the path to update the field
var paths []string;
// SET operation, overwriting the value of info ['update_time']. If the value does not exist, create it
paths = append(paths, "SET info['update_time']");
// PUSH operation. If the value does not exist, create it. If it already exists, report an error
paths = append(paths, "PUSH info['gameid']");
// This is equivalent to SET info['mail']
paths = append(paths, "info['mail']");
// Execute the modification, which is the original sub-operation
api.FieldUpdate(&u, paths);
2.3.3 Deleting & modifying fields
user u; // The user type is the precompiled type of the proto file
// Set primary key
u.id = 1;
// Set the new value of the field to be updated
u.info["update_time"] = "2021-07-01 00:00:00";
// Delete the gameid field and refresh the update_time
var paths []string;
paths = append(paths, "info['update_time']");
paths = append(paths, "POP info['gameid']");
// Execute the modification, which is the original sub-operation
api.FieldUpdate(paths, &u);
2.3.4 Querying fields
user u; // The user type is the precompiled type of the proto file
// Set primary key
t.id = 1;
// Set the path to get the field
var paths []string;
paths = append(paths, "name");
paths = append(paths, "info['update_time']");
// Fill the FieldGet query result in u
api.FieldGet(&u, paths);