BigObjectの特徴と扱い方について

# これは何？
この記事は「[24日後に立派なSalesforceエンジニアになるWEBエンジニア Advent Calendar 2022](https://qiita.com/advent-calendar/2022/kakakaori)」の3日目の記事です。22日後に立派なSalesforceエンジニアになるために今日はBigObjectについて学びます。

# BigObjectとは
大量のレコードを取り扱うためのオブジェクト。
通常のライセンスでは１００万件のデータを取り扱うことができ、追加購入により最大10億レコードまで取り扱うことができるようになる。ディスク使用量はデータストレージは容量で上限が定められていますが、BigObjectsストレージに関してはレコード数により上限が定められている。

# 作り方
手順としてはBigObjectを作る→カスタム項目を作る→インデックスを定義するの流れ。詳細は[こちらのヘルプ](https://help.salesforce.com/s/articleView?id=sf.custom_index.htm&type=5)に記載がある。カスタム項目まで作るとこんな感じになる。
![スクリーンショット 2022-11-29 9.59.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/2ecb3008-5fb3-7985-3eee-4fe47f92f139.png)
作成したBigObjectのサフィックスは「__b」になっているのが確認できる。
この後、赤枠の「新規」ボタンを押してインデックスを作成していくのだが、 **インデックスに指定できる項目は「必須」項目のみのため、必須項目が1つもないときはこのインデックスの「新規」ボタンが表示されない** ので注意。

![スクリーンショット 2022-11-29 21.53.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/915d0375-7185-fff5-c5b9-a1e481d0b73f.png)
インデックスは **一度作成すると削除や編集はできない** ので慎重に考えて設定する必要がある。インデックスに指定する順番もその後のSOQLに影響してくるのでその辺りの考慮事項については後述する。
インデックスを指定すると今までは「開発中」しか選択できなかった「リリース状況」で「リリース済み」が選択できるようになる。

# 各種制限について
大量のデータを処理するために作られているBigObjectにはパフォーマンスに考慮して様々な制約があるので、設計時に把握しておく必要がある。

## サポートされている型が少ない
BigObjectに設定できる項目は以下のように選択できる型に限りがある。
- 参照関係
- URL
- テキスト
- メール
- ロングテキストエリア
- 数値
- 電話
- 日付/時間
選択リスト、数式、チェックボックスなどは扱うことができない。

## SOQLにおける制限がある
- Where に指定できるのはインデックスで定義された項目のみ
- Where に指定できるインデックス項目は1つ目から順番に指定する必要がある
    - 順番を飛ばして2つ目のインデックス項目だけとか、1つ目と3つ目のインデックス項目だけをWhereに指定することはできない
- Where で使える演算子は「=、IN 、<、>、<=、>=」のみ
    - LIKEやNOT　INなど使えない
- Where で複数条件指定するときは最後の条件以外は=にしなくてはいけない
    - IN 、<、>、<=、>=は最後の条件にしか使えない

この辺はちょっと具体例を書きながら見ていく。
今回準備したTest__bに関しては項目は以下のように定義している。
![スクリーンショット 2022-11-29 22.04.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/5f746a3c-d578-bb7e-97d4-b4d0fb33963c.png)

### Where に指定できるのはインデックスで定義された項目のみ
```sql:
-- ○ インデックス定義いる項目を指定
SELECT TestText__c FROM Test__b WHERE TestInt__c = 1
-- hoge

-- × インデックス定義されていない項目を指定
SELECT TestText__c FROM Test__b WHERE TestText__c = 'hoge'
-- [object Object]: TestTel__c FROM Test__b WHERE TestText__c = 'hoge' ^ 
-- ERROR at Row:1:Column:38 field 'TestText__c' can not be filtered in a query call
```

### Where に指定できるインデックス項目は1つ目から順番に指定する必要がある
```sql:
-- ○ 1つ目、2つ目の順で指定
SELECT TestText__c FROM Test__b WHERE TestInt__c = 1 AND TestTel__c = '09012345678'
-- hoge

-- ○ 2つ目、1つ目の順で指定
SELECT TestText__c FROM Test__b WHERE TestTel__c = '09012345678' AND TestInt__c = 1
-- hoge

-- × 2つ目のみ指定
SELECT TestText__c FROM Test__b WHERE TestTel__c = '09012345678'
--[object Object]: Filters may not have any gaps within the composite key
```

### Where で使える演算子は「=、IN 、<、>、<=、>=」のみ
```sql:
-- ○ < を使う
SELECT TestText__c FROM Test__b WHERE TestInt__c < 1
-- moge

-- × LIKE を使う
SELECT TestText__c FROM Test__b WHERE TestInt__c NOT IN (1)
-- [object Object]: Invalid filter. Only =, <, <=, >, >= or IN filters allowed
```

### Where で複数条件指定するときは最後の条件以外は=にしなくてはいけない
```sql:
-- ○ 最後の条件以外は = 
SELECT TestText__c FROM Test__b WHERE TestInt__c = 1 AND TestTel__c IN ('09012345678')
-- hoge

-- × 最初の条件が >
SELECT TestText__c FROM Test__b WHERE TestInt__c > 1 AND TestTel__c IN ('09012345678')
-- [object Object]: Range filter columns must be last in filter in relation to the composite key columns
```

こんな感じでBigObjectはどの項目にどの順番でインデックスを張るかによって検索に関しての制約が出てくるので、インデックスの定義については慎重に考える必要がありそう。しかもインデックスは後から作り直せないので・・・。

# まとめ
後半はBigObjectの制約を多く書いたため「BigObjectってめんどくさそうなやつだな」と思われてしまったかもしれませんが、これらをきちんと理解した上で設計して使用するとすごく便利なものになると思います。特にSalesforceの活用が進んでデータ量が増えてくるといつか役に立つはず！
明日は権限まわりについて学んでいきます。