✍️

Flutter【Supabase】 DB取得 日付絞り込み 、フィルター独自定義(extensionFilterDay() を自作)

2024/02/18に公開

概要

SupabaseのFlutterのSDKを利用して、DBからデータを取得する際に、日付指定して絞り込みたかった。
[以上,以下](.lt(), .gt())を使い、を利用すれば実現できる。
が、ちょっと手間なので、日付絞り込みを、Extensionで独自拡張して対応しました。

対応後の実装( extensionFilterDay()を自作)

    final todayDate   = DateTime.now().toUtc() // 当日のDateTimeを作成

    final res = await Supabase.instance.client
        .from("my_table") // テーブル名
        .select()        // GET
        .extensionFilterDay("created_at", todayDate) // 日時で絞る

もともとの処理

    final todayDate   = DateTime.now().toUtc() // 当日のDateTimeを作成
    final nextDayDate = dayDateUTC.add(Duration(days: 1)); // 次の日のDateTimeを作成

    // "yyyy-MM-dd"の文字列に変換
    final outputFormat = DateFormat('yyyy-MM-dd');
    final startDateString = outputFormat.format(startDayDate);
    final nextDateString = outputFormat.format(nextDayDate);

    final res = await Supabase.instance.client
        .from("my_table") // テーブル名
        .select()        // GET
        .gte("created_at", startDateString) // 日時で絞る(greater than or equal, '<=')
        .lt("created_at", nextDateString)   // 日時で絞る(less than, '>')
  • 冗長な箇所
    • 2つのFilterの指定が必要。( '<=' , と '>' の演算子)
    • 引数に文字列変換が必要(Datetime -> 'yyyy-MM-dd'形式のString)

extensionで独自拡張を作成

日付にまつわる絞り込み処理を、下記2つ定義してExtensionを作成する

  • 1, 日付を1日指定して絞り込む処理(.extensionFilterDay(date)
  • 2, 日付を期間で指定して絞り込む処理(.extensionFilterDateRange(start, end))

// SupabaseのFilterの独自拡張を定義
extension PostgrestFilterBuilderExtensions on PostgrestFilterBuilder {

  // 「指定した日付(UTC)で絞り込む」拡張処理
  // ex)
  // - 'created_at'を、現在の日付(UTC)で、絞りこむ例
  //  .select()
  //  .extensionFilterDay('created_at', DateTime.now().toUtc())
  PostgrestFilterBuilder extensionFilterDay(String columnCreatedAt,
      DateTime dayDateUTC) {
    final startDayDate = dayDateUTC;
    final nextDayDate = dayDateUTC.add(Duration(days: 1)); // add one day

    // cast [DateTime] to ['yyy-MM-dd' String].
    // ---
    final outputFormat = DateFormat('yyyy-MM-dd');
    final startDateString = outputFormat.format(startDayDate);
    final nextDateString = outputFormat.format(nextDayDate);
    print(
        "add date Filter:  [ $startDateString <= ] && [ > $nextDateString ] ");
    // ---

    // add filter ( startDayDate <= 'targetDay' && 'targetDay' > nextDayDate )
    return this
        .gte(
        columnCreatedAt, startDateString)     // filter by day(greater than or equal, '<=')
        .lt(columnCreatedAt, nextDateString); // filter by day(less than, '>')
  }

  // 「指定した日付(UTC)のレンジで絞り込む」拡張処理
  // NOTE: the parameter 'endDayDateUTC' is '>=', so it is contained date.
  // ex)
  // - 'created_at'を、日付(UTC)で、絞りこむ例
  //
  // final twoDaysBefore = DateTime.now().toUtc().add(Duration(days: -2))
  // final twoDaysAfter = DateTime.now().toUtc().add(Duration(days: 2))
  //
  // .select()
  // .extensionFilterDayRange('created_at', twoDaysBefore, twoDaysAfter)
  PostgrestFilterBuilder extensionFilterDateRange(String columnCreatedAt, DateTime startDayDateUTC, DateTime endDayDateUTC) {

    // cast [DateTime] to ['yyy-MM-dd' String].
    // ---
    final outputFormat = DateFormat('yyyy-MM-dd');
    final startDateString = outputFormat.format(startDayDateUTC);
    final endDateString = outputFormat.format(endDayDateUTC);
    print("add date Filter:  [ $startDateString <= ] && [ >= $endDateString ] " );
    // ---

    // add filter ( startDayDate <= 'targetDay' && 'targetDay' => nextDayDate )
    return this
        .gte(columnCreatedAt, startDateString)  // filter by day(greater than or equal, '<=')
        .lte(columnCreatedAt, endDateString);   // filter by day(less than or equal, '>=')
  }

}

// ex)1日の日付で絞る実装

    final todayDate   = DateTime.now().toUtc() // 当日のDateTimeを作成

    final res = await Supabase.instance.client
        .from("myTable") // テーブル名
        .select()        // GET
        .extensionFilterDay("created_at", todayDate) // 日時で絞る

// ex)期間で絞る実装

    final todayDate   = DateTime.now().toUtc() // 当日のDateTimeを作成
    final oneWeekLaterDayDate = dayDateUTC.add(Duration(days: 7)); // add one day

    final res = await Supabase.instance.client
        .from("myTable") // テーブル名
        .select()        // GET
        .extensionFilterDayRange("created_at", todayDate, oneWeekLaterDayDate) // 日時を期間で絞る

所感

個人的には、FirebaseのDB(Firestore)と比べると、SupabaseのDBの方がデータ操作ををサクサク実装できるので嬉しい😀
 FirebaseFirestoreだと、NoSQLだったりするので、Firebase導入プロジェクトでも、DBだけは「Supabase」で対応、というような両方利用するパターンを採用してみた。
 将来的に、DBの移行作業があったとしても、Firestoreより、Supabaseの方が多く人にとってやりやすいのではないかな、とも思いました。

その他

適用されたフィルターを、Debug時にPrintして確認したかったが、それようの機能?がなさそう?
調べきれてないかもですが。。。

// イメージ

    final res = await Supabase.instance.client
        .from("awesome_table") // テーブル名
        .select()        // GET
        .order("awesome_column1") // ソート
        .order("awesome_column2") // ソート
        .limit(100)               // 最大取得件数を指定
        .debugPrint() // <- これつけると、「Debug」時に、↑の設定をログはいてくれるイメージ

// ↓の debugフラグを試したが、期待した設定のログ出力はなかった。。

/// ↓ debugのコメント定義
/// If [debug] is set to `true`, debug logs will be printed in debug console.

        await Supabase.initialize(
          url: Env.supabaseUrl,
          anonKey: Env.supabaseApiKey,
          debug: true, // <- これつけたけど、↑のような細かな条件は出力されないみたい
        );

Discussion