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 as info["sub_map"]["sub_key"] or info["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);

results matching ""

    No results matching ""