1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

マルチインデックステーブルのセカンダリインデックスを使ってフィルターする

Last updated at Posted at 2018-12-14

マルチインデックステーブルを使う時、基本的にはプライマリーキーでレコードを特定して操作していますが、それ以外の条件で検索する場面もやはりあるので、セカンダリーインデックスの使い方を調査してみました。

定義

ポイントは2つあります。

  • 1つ目は、マルチインデックステーブルの構造体を定義する時、セカンダリーインデックス用の関数を定義する必要があります
  • 2つ目は、マルチインデックステーブルの type を定義する時、セカンダリーインデックスの定義情報を追加する必要があります
struct [[eosio::table]] person {
  uint64_t id;
  string name;
  uint64_t age;
  string address;
  string tel;

  auto primary_key() const { return id; }
  uint64_t get_age() const { return age; } // ① get_age 関数を追加
};

// ② index_by 部分を追加
typedef eosio::multi_index<"people"_n, person, indexed_by<"age"_n, const_mem_fun<person, uint64_t, &person::get_age>>> address_index;

cleos get table で使う

# デフォルトで条件なしで、プライマリーキーでソートされる
$ cleos get table addressbook addressbook people
{
  "rows": [{
      "id": 0,
      "name": "山田",
      "age": 38,
      "address": "横浜",
      "tel": "0451113333"
    },{
      "id": 1,
      "name": "田中",
      "age": 29,
      "address": "渋谷",
      "tel": "031112222"
    },{
      "id": 2,
      "name": "山本",
      "age": 45,
      "address": "品川",
      "tel": "0333334444"
    }
  ],
  "more": false
}

# --index で使うインデックス番号を指定すると、そのインデックスでソートされる
$ cleos get table addressbook addressbook people --key-type i64 --index 2
{
  "rows": [{
      "id": 1,
      "name": "田中",
      "age": 29,
      "address": "渋谷",
      "tel": "031112222"
    },{
      "id": 0,
      "name": "山田",
      "age": 38,
      "address": "横浜",
      "tel": "0451113333"
    },{
      "id": 2,
      "name": "山本",
      "age": 45,
      "address": "品川",
      "tel": "0333334444"
    }
  ],
  "more": false
}

# --lower でインデックス範囲の `from` を指定できる
$ cleos get table addressbook addressbook people --key-type i64 --index 2 --lower 30
{
  "rows": [{
      "id": 0,
      "name": "山田",
      "age": 38,
      "address": "横浜",
      "tel": "0451113333"
    },{
      "id": 2,
      "name": "山本",
      "age": 45,
      "address": "品川",
      "tel": "0333334444"
    }
  ],
  "more": false
}

# --upper でインデックス範囲の `to` を指定できる
$ cleos get table addressbook addressbook people --key-type i64 --index 2 --lower 30 --upper 40
{
  "rows": [{
      "id": 0,
      "name": "山田",
      "age": 38,
      "address": "横浜",
      "tel": "0451113333"
    }
  ],
  "more": false
}

アクションで検索

[[eosio::action]]
void search(uint64_t age) {
  address_index addresses(_code, _code.value);

  auto age_index = addresses.get_index<"age"_n>();
  auto itr = age_index.lower_bound(age); // age 以上のデータを検索

  for (; itr != age_index.end(); itr++)
  {
    print("id: ", itr->id, " name: ", itr->name, " age: ", itr->age, "\n");
  }
}

アクションを呼び出すと下記になります。
トランザクション呼び出しのコンソールには1つ目の print結果だけ表示されていますが、nodeos側のログには想定どおりに該当データ分全部表示されています。

$ cleos push action addressbook search '[30]' -p addressbook
executed transaction: 9f95fc9f805526664867048660ef825f7f8dd846f3b1c509a813c2adcd597aa8  104 bytes  9412 us
#   addressbook <= addressbook::search          {"age":30}
>> id: 0 name: 山田 age: 38
warning: transaction executed locally, but may not be confirmed by the network yet         ]

# nodeos 側のログを確認すると下記になります
debug 2018-12-12T21:42:06.546 thread-0  apply_context.cpp:28          print_debug          ]
[(addressbook,search)->addressbook]: CONSOLE OUTPUT BEGIN =====================
id: 0 name: 山田 age: 38
id: 2 name: 山本 age: 45

[(addressbook,search)->addressbook]: CONSOLE OUTPUT END   =====================

制限

  • セカンダリーインデックスのデータ型は下記の型だけ
idx64 - Primitive 64-bit unsigned integer key
idx128 - Primitive 128-bit unsigned integer key, or a 128-bit fixed-size lexicographical key
idx256 - 256-bit fixed-size lexicographical key
idx_double - Double precision floating point key
idx_long_double - Quadruple precision floating point key
name 特別に、アカウントもサポートされている
  • セカンダリーインデックスは、最大 16 個までしか作成できません
  • 検索時は、範囲指定しか出来ません

まとめ

プライマリーキー以外に、セカンダリーインデックスを活用することで、他の条件でも検索出来ます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?