🦋

Serverpod ~ForeignKeyはNullableという発見

2023/09/01に公開

fieldにNullがあってはいけない、と聞いたので

必死にtable構成を考えて、中間tableを作って、
そしたらSeverpodがJOIN未実装と言われて・・・という話は前にも書いた。

しっかり勉強してから実行、という性格ではないので、ときどきひどく遠回りをする。
今回など、その典型だろう。
中間tableをつくりまくりながら、
いくらコンピューターの仕事が早いといっても、なんか変だな、と思っていた。
イベント会場でこんな動線を引いたら、絶対混乱する。

で、新しいtutorial動画を見ていたら、あれnullableのfield作ってる!?
しかも、Listをいれたfieldまである!
で、改めて調べたら、ForeignKeyはNullableって、
JOINは重いですからねえって、
Serverpodの独自機能ってわけじゃない、SQLの常識だったらしい。

早く言ってよ〜(基礎勉強しろ!)

Listの対応についてはまだよくわからないのだが、
少なくとも一対一対応で、
Null対策のためだけにつくった中間tableは撤廃した。
これでendpointを書けば、外部キーでの絞り込みがOneStepでできる。

Chipで選んだキーワードのIdをListにして絞り込み

こんなふうにprotocolに外部キーを入れて

class: Principal
table: principal
fields:
  annee: int
  affair: String
  pays: String
  placeId: int?, parent=places
  cattId: int?, parent=countryatts
  pattId: int?, parent=placeatts

こんな関数をendpointに書いて

  Future<List<Principal>> getPrincipalByCatt(Session session, {List<int>? keynumbers}) async {
    print("Getting principal with cattIds: $keynumbers");

    var whereClause;

    if (keynumbers != null && keynumbers.isNotEmpty) {
      for (var keynumber in keynumbers) {
        if (whereClause == null) {
          whereClause = Principal.t.cattId.equals(keynumber);
        } else {
          whereClause = whereClause | Principal.t.cattId.equals(keynumber);
        }
      }
    } else {
      whereClause = Constant(true);
    }

    return await Principal.find(
      session,
      where: (_) => whereClause,
      orderBy: Principal.t.annee,
    );
}

Flutter側はこんな感じ

import 'package:flutter/material.dart';
import 'package:acorn_client/acorn_client.dart';
import 'package:serverpod_flutter/serverpod_flutter.dart';

class SearchByOptionsModel extends ChangeNotifier {
  var client = Client('http://localhost:8080/')
    ..connectivityMonitor = FlutterConnectivityMonitor();


  List<Principal> _principal = [];
  
  List<Principal> get principal => _principal;
  List<Principal> get principalByPlaces => _principal;


  fetchPrincipal({List<String>? countries}) async {
    try {
      _principal = await client.principal.getPrincipal(keywords: countries);
      print("Getting principal with keywords: $countries");
      notifyListeners();
    } on Exception catch (e) {
      debugPrint('$e');
    }
  }

  fetchPrincipalByPlaces({List<int>? listPlaceIds}) async {
    try {
      _principal = await client.principal.getPrincipalByPlaces(keynumbers: listPlaceIds);
      print("Getting principal with keynumbers: $listPlaceIds");
      notifyListeners();
    } on Exception catch (e) {
      debugPrint('$e');
    }
  }
}

もっとシンプルにできそう

Serverpodのtable構成変更はそんなに難しくないが(自動生成でどんどん変わっていくから)
PostgreSQL側は手作業で「そこは直せません」とか言われるので、
真面目な方は、よく考えてから作り始めましょう\(^O^)/

Flutter大学

Discussion