【qp】画像をアップロードできないバグを修正

 9月11日の日報です。qpはquelplanの略か何かです。

firestoreクエリで array-contains は1回のみ

 オレオレ画像アップローダー quelplan には「複数タグによる絞り込みをfirestore完結で行う」という要件があります。そういう機能はRDBなりLucene系なりでやれという話はあると思うんですが、まあそれは実験的プロジェクトいうことで進めています。

 さて、この機能を実現するにあたって、firestoreクエリに新しく追加された array-contains を利用しようと考えていました。タグ文字列を配列で持たせて、クエリで取ってこようということです。簡単そうですよね。

 ところが実際に動かしてみると、タグ1つの時はいいのですが、2つだと落ちます。どうやら array-contains 複数回使うことができず、クエリ1つにつき1回しか使えない… みたいです。ドキュメントが見つからないのですが、SDKのテストにあるので、そういう仕様なんだろうなあという感じですね。

validationIt(
  persistence,
  'with multiple array-contains filters fail.',
  db => {
    expect(() =>
      db
        .collection('test')
        .where('foo', 'array-contains', 1)
        .where('foo', 'array-contains', 2)
    ).to.throw(
      'Invalid query. Queries only support a single array-contains filter.'
    );
  }
);

 仕方がないので、古式ゆかしいオブジェクト形式に戻しました。

# create
const tags: { [key: string]: boolean } = {};
for (const tag of props.tags) {
  tags[tag] = true;
}
await db
  .collection("files")
  .doc("users")
  .collection(this.$firebase.auth().currentUser.uid)
  .add({
    name: props.name,
    path: props.path,
    tags,
    createdAt: firebase.firestore.FieldValue.serverTimestamp(),
    lastUpdatedAt: firebase.firestore.FieldValue.serverTimestamp()
  });

# search
let query: firebase.firestore.Query = db
  .collection("files")
  .doc("users")
  .collection(this.$firebase.auth().currentUser.uid)
  .limit(100);

// search by tags
for (const tag of state.tags) {
  query = query.where(`tags.${tag}`, "==", true);
}

 ドキュメント欲しいですね… あるのかもしれませんが、見つからないのでつらい。

 ちなみに、firebaseの公式日本語ドキュメントは読まない方がいいです。英語版には書いてある情報が、日本語版では項目ごとなかったりします。array-contains もまだないかも?