🔥

Node.jsでfirestore(datastoreモード)を使う。

2024/02/17に公開

@google-cloud/datastoreを使いましたが、色々悩むところがありました。
その時の覚書になります。

データ取得例

import { Datastore } from '@google-cloud/datastore';

const store = new Datastore({
    namespace: "TestDB",
    credentials: credential, // jsonから読み込んだ内容を指定する
    projectId: credential.project_id,
});

const query = store
      .createQuery('Sample')
      .filter('testId', '=', "test123");

const [results] = await store.runQuery(query);
console.log(results);

const query = store
      .createQuery('Sample')
      .filter('testId', '=', "test123")
      .filter('createdAt', '<=', targetDate);

const [results2] = await store.runQuery(query);

上記では、testIdだけで検索する例とtestIdとcreatedAtを組み合わせて検索する例を示しました。この時、testIdとcreatedAtに対して複合インデックスが貼られていない場合は2つ目の検索実行時にエラーとなります。

データ更新例

    await store.update({
      key: record[store.KEY],
      data: [
        ...Object.keys(record).map((key) => {
          return {
            name: key,
            value: record[key],
            excludeFromIndexes: !indexKeys.includes(key),
          };
        }),
        {
          name: 'sampleAmount',
          value: 1000,
          excludeFromIndexes: true,
        },
      ],
    });
  • キーの指定
    例では次のように一度取得したレコードに付与される一意に特定できるキーからレコード更新を行っています。
key: record[store.KEY],
  • インデックス
    excludeFromIndexesを指定することで、インデックスが貼られなくなります。インデックスが多ければ多いほどコストがかかるので必要なものだけに絞りましょう

ただし、例で次のように書いた通り、複合インデックスにあたるプロパティについてはインデックスを付ける必要があります。(indexKeysに複合インデックスを文字列の配列で定義し、includesで該当する場合はインデックスを付与します)

excludeFromIndexes: !indexKeys.includes(key),

当初、複合インデックスはユーザー指定インデックスと関係なく付与されるものと誤解していましたが、エンティティ作成時にインデックス指定していないと複合インデックスからも漏れるようです。

余談ですが、コンソールからエンティティを検索しようとするとき、インデックスがついてる項目をソートするとインデックスが無いエンティティは表示から除外されるので注意です(削除されたかのように錯覚します)。
同じプロパティ名であってもインデックス有り無しが混在しうるのがfirestore(datastoreモード)です。

  • update文を書く時の注意
    途中Object.keysのループを作っていますが、updateでsampleAmountの項目だけ更新しようとループ部分を削除すると、sampleAmount以外のプロパティが消えます

Discussion