📜  eosio 多索引二级索引 - C++ (1)

📅  最后修改于: 2023-12-03 15:00:36.529000             🧑  作者: Mango

eosio 多索引二级索引 - C++

在 EOSIO 中,多索引表及其二级索引是非常有用的概念。它们允许开发人员在智能合约中轻松地创建和操作具有复杂数据结构的表。

什么是多索引表?

EOSIO 的多索引表(multi-index table)是一个支持多个索引和迭代器的数据表。它是一个由 C++ STL 容器实现的智能合约库。

多索引表支持以下类型的索引:

  • 主键索引:使用表中的某个字段作为唯一标识符。
  • 二级索引:使用多个表中的字段作为查询条件。
什么是二级索引?

在 EOSIO 中,二级索引(secondary index)是在多索引表中定义的额外索引,它允许用户查询表中的数据而不仅仅是使用主键。在使用二级索引之前,我们需要使用一个辅助表来跟踪其余键对应的主键。

使用 C++ 编写多索引表

在开始编写多索引表代码之前,我们需要在 contract.hpp 文件中声明一个 struct 作为表。

// 定义 struct 作为表
struct [[eosio::table]] person {
    // 表中的字段
    uint64_t id;
    std::string name;
    uint32_t age;
    
    // 定义主键索引
    uint64_t primary_key() const { return id; }

    //定义二级索引
    uint64_t get_secondary_1() const { return age; }
};

在上述代码中,我们定义了一个 person struct,其中包含三个表字段,每个字段的类型分别是 uint64_tstd::stringuint32_t。然后,在 person struct 中,我们定义了一个用于主键索引的函数 primary_key(),并定义了一个用于第一级二级索引的函数 get_secondary_1()

接下来,我们需要在智能合约的 CPP 文件中实现上述 struct 的多索引表。我们使用一个 typedef 声明多索引表类型,并在智能合约中定义多索引表服务。

// 定义多索引表类型
typedef eosio::multi_index<"person"_n, person,
    indexed_by<"byage"_n, const_mem_fun<person, uint64_t, &person::get_secondary_1>>
> people_table;

class [[eosio::contract]] mycontract : public eosio::contract {

public:
    mycontract(name self, name code, datastream<const char*> ds)
        : eosio::contract(self, code, ds) {}

    // 定义多索引表服务
    [[eosio::action]]
    void addperson(std::string name, uint32_t age) {
        // 获取智能合约的 require_auth() 权限
        require_auth(get_self());

        // get_self() 获取智能合约自己的 name
        // 用 people_table 调用 emplace() 函数把数据放到表里面
        people_table people(get_self(), get_self().value);
        people.emplace(get_self(), [&](auto& p) {
            p.id = people.available_primary_key();
            p.name = name;
            p.age = age;
        });
    }
};

在上面的 mycontract 类定义中,我们定义了一个名为 people_table 的多索引表类型,它具有 person struct 的类型和一个名为 "byage" 的二级索引。然后我们在定义的 mycontract 类中定义了一个名为 addperson() 的多索引表服务,在此服务中可以往多索引表 people_table 中添加人员。

如何查询二级索引?

我们可以使用 get_index() 函数获取一个多索引表的已知索引类型,接着可以使用 .find().lowerbound() 等函数从此索引中查询数据。

// 获取 mycontract 实例的多索引表
people_table people(get_self(), get_self().value);

// 获取索引类型为 "byage" 的二级索引
auto people_by_age = people.get_index<"byage"_n>();

// 查询年龄大于 18 岁的人员
auto itr = people_by_age.lower_bound(18);

while (itr != people_by_age.end()) {
    // 处理查询到的数据
    itr++;
}

在上面的示例代码中,我们查询多索引表 people_table 的二级索引 "byage" 中年龄大于 18 岁的人员。我们首先创建一个 people 变量来获取 mycontract 实例的多索引表,然后使用 .get_index() 函数获取 "byage" 索引,最后使用 .lowerbound() 函数查询真正的数据。

需要注意的是,如果您已经使用了二级索引功能,则还应该为其定义一个辅助表,在辅助表中存储与每个索引值关联的人员 ID。这样做可以加快查询速度,但可能会增加一些复杂性。

结论

多索引表和二级索引是 EOSIO 及其智能合约库提供的强大功能,如果您想开发复杂的数据结构,请务必尝试使用它们。在编写智能合约时,您可以使用上述示例代码作为参考,并在合约中添加自己的多索引表和二级索引。