EOS入門指南PART7——如何操做multi_index

上一章咱們學習了對智能合約開發來講相當重要的第一步:c++

  • 知道了RAM、multi_index和EOS數據庫各是什麼以及它們之間的關係;
  • 知道了multi_index是內存數據庫的入口;
  • 瞭解了multi_index內部的結構長什麼樣子;

今天這章,主要介紹multi_index的相關操做,趁機鞏固一波上一章學習到的理論知識。數據庫

摘要

上一章說到multi_index的概念——多索引容器,multi_index容器的內部結構能夠類比成傳統數據庫裏的一張表,只不過這張表只有一列,每一行都是一個struct結構體。dom

這一章就要向你們介紹,如何具體使用multi_index。函數

primary keys

仍是上一章中的例子:學習

eos_iterator

multi_index的容器(表)裏每一行都是上面的struct結構體,而且都是按照主鍵升序排列。因此每個multi_index中會有一個默認索引,也就是主鍵。如上圖,就是按照主鍵(pkey)升序排列的。ui

uint64_t primary_key() const { return pkey; }

通常而言,在struct結構體中會聲明一行得到主鍵的方法primary_key(),這裏定義了主鍵類型爲uint64_t,返回結構體中的pkey字段,即pkey這個字段就是整個結構體的主鍵。spa

自定義索引

既然叫multi_index,確定不僅能夠根據主鍵進行索引,事實上,咱們還能夠自定義索引。例如能夠在結構體中定義以下方法:code

account_name get_customer() const {
    return customer;
}

這就是咱們自定義的索引。仿照以前的primary_key()能夠看到,這個方法返回值的類型爲account_name,返回的字段爲customer。固然自定義的索引並不必定要返回結構體中的某個字段的變量,也能夠將變量之間的運算結果做爲索引。blog

這裏先貼上結構體的完整表達,方便下面介紹如何使用多索引:索引

struct service_struct {
     uint64_t pkey;
     account_name customer;
     Date date;
     uint32_t odometer;
    
    auto primary_key() const {return pkey;}
    account_name get_customer() const {return customer;}
    
    EOSLIB_SERIALIZE(service_struct,( pkey )( customer )( date )( odometer ))
}

typedef eosio::multi_index<service, service_struct,
    index_by<N(bycustomer), const_mem_fun<service_struct,account_name, &service_struct::get_customer>
    >
> customer_index;

解釋一下,使用上面的方式來定義索引,eosio::multi_index<...>的參數解釋以下:

  • service : multi_index容器的表名(如上圖)
  • service_struct : 智能合約重定義的struct結構體名稱,也能夠理解成表中的一行記錄;
  • indexed_by<...>

    • N(bycustomer) : 給索引發個名字 - bycustomer
    • const_mem_fun<...> :

      • account_name : 索引的類型
      • &service_struct::get_customer:經過service_struct結構體中的get_customer函數得到(索引)

經過上述表達,就能夠再生成一張按customer爲索引的表bycustomer(見本文第一張圖)。左邊是按照主鍵索引的原表service,右邊的表就是咱們按照customer的索引生成的新表(按customer從小到大進行排列),能夠看到新表內的行內容和以前是一行的(見虛線指向原表),只不過按照customer字段進行了從新排列。

這裏定義了customer_index類型,這樣之後就能夠直接用這個類型去初始化真正的multi_index表。

迭代器

上一章咱們介紹過迭代器,能夠把迭代器想象成一個電梯,經過在索引中上下滑動來定位數據。接着上面介紹的自定義索引comstomer_index:

account_name customer_acct = eosio::chain::string_to_name(customer_name);
auto cust_itr = customer_index.find(customer_acct);

經過上述代碼,咱們就能夠找到bycustomer表中,customer爲某個特定值的全部行(結構體)了。好比,第一張圖中,若是傳入的參數爲"bob",那就能夠找出全部customer爲bob的數據了,放入迭代器裏。經過迭代器就能夠逐條獲取咱們想要的數據信息。

獲得了迭代器以後,我們再來看看怎麼使用迭代器:

while(cust_itr != service.end() && cust_itr -> customer == customer_acct) {
    // code to execute
    cust_itr++;
}

其中cust_itr != service.end()表示迭代器並無走到service表的結尾,&&以後也很容易看懂,再篩選customer的值。每次小的遍歷結束是,迭代器+1,表示繼續訪問迭代器中的下一行。

索引和迭代器如何配合工做

經過上面的介紹,你們應該就能夠理清multi_index和迭代器是如何配合工做的:

i經過multi_index能夠獲得一張按照特定字段索引的表,再經過對索引設置一些條件,就能夠篩選獲得一些迭代器,再經過對迭代器的遍歷,就能夠訪問咱們想要訪問的數據了。

multi_index的初始化

上文關於multi_index多與定義有關,如今終於要開始實例化multi_index了。

multi_index(uint64_t code, uint64_t scope)

在上面的初始化(實例化)的語句中,能夠看到有兩個參數:

  • code -擁有這張multi_index表的帳戶,該帳戶擁有對合約數據的讀寫權限;
  • scope - 用戶帳戶名下的區域。能夠在code下定義多個scope,把屬於不一樣scope的表隔離開;

這裏的code和scope,都是用來爲表創建訪問權限的。

因此要想初始化上面的customer_index,可使用:

// customer_index 就是以前 typedef 定義的類型
// bycustomer就是新表
// _self就是當前調用方法的帳戶
customer_index bycustomer(_self, _self);

添加 - emplace

這裏順便說一下find,multi_index使用.find來查詢,代碼接上往下寫:

void demo::create(const uint64_t id,
                  const account_name cust_acct,
                  const Date date,
                  const uint32_t odometer) {
    // 找出特定值的customer的數據
    // 這裏的auto至關於其餘語言中的var,聲明變量時不指定類型
    auto itr = bycustomer.find(cust_acct);
    // 查詢customer = cust_acct的記錄並要求該記錄不存在
    // 由於primary_key不能重複
    // 因此插數據以前先查詢一下,保證不重複
    eosio_assert(itr == profile.end(), "Account already exists");
    // 往索引裏添加記錄
    bycustomer.emplace(cust_acct, [&](auto& c)) {
        c.pkey = id;
        c.customer = cust_acct;
        c.date = date;
        c.odometer = odometer;
    }
}

其中[&](auto& c)是c11以後一種新的lambda表達式,有興趣的同窗能夠自行深刻了解,這裏簡單介紹一下,這個表達式大概表示:

除了該函數已有的參數,其餘的參數例如 id, date, odometer這些,都是在上層的做用域中經過引用的形式傳入函數內。

其中auto咱們以前說過,表示不限制類型,可是也爲引用。

看懂了添加記錄,其餘諸如刪、改、查的操做也就不難看懂了,你們能夠去官網查看相關例子:

https://eosio-cpp.readme.io/d...

結束語

本章咱們學習了:

  • 如何自定義索引;
  • 如何生成以及使用迭代器;
  • 索引和迭代器是如何配合使用的;
  • multi_index的相關操做

但願你們學完以後能夠去官網繼續補充刪、改、查的相關例子,以達到觸類旁通的效果。下面幾篇咱們將正式瞭解EOS智能合約開發的二三事。

相關文章
相關標籤/搜索