LoginSignup
0
0

More than 1 year has passed since last update.

Firestoreでクエリする

Posted at

学ぶ

何度見ても制限事項が多すぎる。
考えることを減らすために、エラーになるクエリを補正する関数を書いていたが、流石に毎回そこそこな量の補正関数が走るのはマズいと思ったため、そのようなパターンはテストで頑張って潰す方が現実的ということになった。

ちょっとだけ分かりやすくする

以下のような型を作成

import type {
  Query,
  DocumentData,
  OrderByDirection,
  WhereFilterOp,
  FieldPath,
} from 'firebase/firestore';

export type CustomQuery<T> = {
  target: Query<DocumentData>;
  where?: {
    field: FieldPath | keyof T;
    operator: WhereFilterOp;
    value: unknown;
  }[];
  orderBy?: {
    field: FieldPath | keyof T;
    direction: OrderByDirection;
  }[];
  start?: {
    cursor: 'at' | 'after';
    value: unknown[];
  };
  end?: {
    cursor: 'at' | 'before';
    value: unknown[];
  };
  limit?: {
    toLast?: boolean;
    limit: number;
  };
};

上の型を利用して以下の関数で整形することで、これらの恩恵が得られる。

  • orderByをstart,endに対するクエリの前に確実に配置できる
  • start, end, limitに対して確実に最大1つのクエリを受け付ける
  • いちいちメソッドをimportしなくていい
  • jsonで管理できるのでいろいろと便利
import {
  endAt,
  endBefore,
  limit,
  limitToLast,
  orderBy,
  query,
  startAfter,
  startAt,
  where,
} from 'firebase/firestore';

import type { CustomQuery } from '@/hooks/useFirestore';

import type { FieldPath } from 'firebase/firestore';

export const formatCustomQuery = <T>(customQuery: CustomQuery<T extends (infer U)[] ? U : T>) => {
  const whereConstraints =
    customQuery.where?.map((whereConfig) =>
      where(whereConfig.field as string | FieldPath, whereConfig.operator, whereConfig.value)
    ) ?? [];

  const orderByConstraints =
    customQuery.orderBy?.map((orderByConfig) =>
      orderBy(orderByConfig.field as string | FieldPath, orderByConfig.direction)
    ) ?? [];

  const startConstrains = customQuery.start
    ? customQuery.start.cursor === 'at'
      ? [startAt(...customQuery.start.value)]
      : [startAfter(...customQuery.start.value)]
    : [];

  const endConstrains = customQuery.end
    ? customQuery.end.cursor === 'at'
      ? [endAt(...customQuery.end.value)]
      : [endBefore(...customQuery.end.value)]
    : [];

  const limitConstraints = customQuery.limit
    ? customQuery.limit.toLast
      ? [limitToLast(customQuery.limit.limit)]
      : [limit(customQuery.limit.limit)]
    : [];

  const formatedQuery = query(
    customQuery.target,
    ...whereConstraints,
    ...orderByConstraints,
    ...startConstrains,
    ...endConstrains,
    ...limitConstraints
  );

  return formatedQuery;
};

いちいち公式リファレンスを見るのもあれなので、重要なところはローカルにドカっとコピペした。
以上。

0
0
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
0
0