fukamachi / mito

An ORM for Common Lisp with migrations, relationships and PostgreSQL support
292 stars 31 forks source link

select-daoにrelated節を追加 #62

Closed cxxxr closed 4 years ago

cxxxr commented 4 years ago
(defclass hoge ()
  ((id :initarg :id :accessor hoge-id))
  (:metaclass dao-table-class))

(defclass hoge-relation ()
  ((hoge-id :initarg :hoge-id :accessor hoge-piyo-hoge-id)
   (value :initarg :value :accessor hoge-relation-value))
  (:metaclass dao-table-class))

というdaoがあるとしてhoge-relationのvalueを見て条件にあったhogeのリストを取得した後、 hogeにhoge-relationのvalueも含めたオブジェクトを作ろうとすると、更にfind-daoしないと hoge-relationのオブジェクトが得られずN+1問題が置きてしまいます。 hogeの中のスロットにhoge-relationがあるとselect-daoにincludesを追加すればいいですが そうでない場合にも同じことが出来るようにrelated節を追加しました。

変更点としてはselect-daoの三つ目の返り値を追加し、ベクタの中にrelatedに指定したクラスの順番に結果が入るようにしました。 ppcre:scan等と同じ形式です。

* (select-dao 'hoge
    (related 'hoge-relation)
    (left-join 'hoge-related :on (:= :hoge_relation.hoge_id :hoge.id))
    (where (:= :hoge_relation.value value)))

=> (#<hoge {0}> #<hoge {1}> #<hoge {2}>)
   #<sxql-statement: ...> 
   #((#<hoge-relation {3}> #<hoge-relation {4}> #<hoge-relation {5}>))
fukamachi commented 4 years ago

レコードがone to oneではなくone to manyのときはどうなりますか?

cxxxr commented 4 years ago

assertionしてone to oneの場合以外はエラーを出すようにするのはどうですか

fukamachi commented 4 years ago

assertionしてone to oneの場合以外はエラーを出すようにするのはどうですか

one to many の場合は related のカバー範囲ではないということ? N+1クエリを解決したいという意図はわかったのだけど、one to manyの場合はサポートしないのはなぜですか? N+1クエリになるのは同じだと思うのですが

fukamachi commented 4 years ago

includes のコンセプトと同じだと思うので、まとめられるなら (実装上の不都合がないなら) まとめてしまいたいと思っている。

cxxxr commented 4 years ago

そもそも上の例だとhogeテーブルのカラム名はidなのにhoge-relationのカラムはhoge-idなので 正しいhoge-relationが作られない問題がありました relatedの指定にカラム名も加えないとだめそうです

cxxxr commented 4 years ago
(related table-name :key :uuid)

というようにkeyを指定するようにしました

cxxxr commented 4 years ago

one to manyだとしても多値の一つ目と三つ目のベクタの中の各リストをhogeとhoge-relationのペアとして扱えるので問題ないはずです

cxxxr commented 4 years ago

includesとまとめるとincludeに指定したテーブル名によって三つ目の返り値が変動して紛らわしいので別ものとして扱うほうがよさそうです

cxxxr commented 4 years ago

forkしたリポジトリで使って仕様を揉んでから本家に反映させることになったのでclose