DgraphのORマッパー"graphor"を作りました

こんにちは。nosukeruと申します。

趣味(?)でやっているアプリ開発の方で、バックエンドをGoとDgraphというグラフデータベース(https://dgraph.io/)を使って構築しているのですが、如何せんDgraphが新しいサービスなために日本語文献が少なく、またライブラリもあまり充実していない状況で、Go公式のDgraphクライアントも素のGraphQL+-*1を書いて投げるものしかなかったので、自分でGo用のORM(Object Relational Mapper)を実装してみました。PHPのLaravelを以前触ったことがあったので大部分を参考にして仕様などを決めました。

元々は自分用に使うつもりしかなかったのですがせっかく作って置いておくのももったいないので公開しようと思います。もしグラフデータベース、Dgraphに興味がある方がいましたらぜひフィードバック等頂ければ大変助かります。Issue/PRも歓迎です。

github.com

(注意)現在まだベータ版です。特にセキュリティ面(QLインジェクション)には不安があるので使用の際はご注意ください。

以下おまけ(開発で感じたこと)

  • Goのインターフェース・モデル管理が難しい。Modelというインターフェースで統一的に扱えるようにしつつSave()などのモデル共通の機能をどうやって実装するかに相当悩んだ。結局Modelインターフェースとそれを実装するModelPropertyを定義して、ユーザー定義のモデルにModelPropertyを組み込んでもらうことで実現した。ただクエリ結果をそれぞれのモデルにキャストする部分はジェネリクスなしでは厳しく、クエリ結果をそれぞれのモデルとして取得するAsUser()AsUsers()をユーザーに定義してもらうしかなさそうという結論になった。

  • エラー処理がめんどくさい。データベースにクエリ投げるたびにエラーが発生しうるので実行系は結局全部エラーが返り値についてくる。panic("DataBaseError")したい気持ちをグッとこらえて頑張ってエラー処理を書いた。ただエラーの粒度をどの程度にしたらいいのかよくわからなかった。

  • QueryとRelationにQueryBuilderとしての共通の処理を持たせるところはinterfaceとstructを使い分けてうまく書けたと思う。やったぜ。

  • シングルトン(graphorInterface)をどのように外部に公開したらいいのかがわからなくて、結局 1. graphorInterfaceを定義 2. 準拠するgraphorStructを定義 3. NewGraphor()で作成したgraphorInterfaceをパッケージ変数としてもつ というよくわからん実装になった。もうちょっとスマートな実装法がないか考えたい。

  • ORMを実装したことでQuery Languageへの理解が嫌というほど身につきました。SQL文わからないよお><って方はぜひ一度自分でORMを実装してみましょう!(崖から突き落として生き残った奴を選別するタイプのオタク)

*1:SQLに当たるデータベース言語