Help us understand the problem. What is going on with this article?

Database.Persist の関数群を簡単に説明

More than 5 years have passed since last update.

Yesod で使われている Database.Persist ですが、どうも型シグニチャとかごちゃごちゃしててわかりにくいので、型を簡略化して説明を加えてみました。
参考: persistent-1.1.3.2

はじめに

型シグニチャは簡略化しています。haddock との対応は

  • val
  • キーKey val
  • ユニークキーUnique val
  • フィルタ[Filter val]
  • オプション[SelectOpt val]
  • 更新内容[Update val]

といった感じです。
また、値とエンティティの違いですが、値はデータベースと関係なく存在するデータとすると、エンティティはデータベース上のレコードに対応し、キーの情報を持っています。
型シグニチャ中の m は、その関数が使えるモナドみたいなもんです…(うまく説明できない)。Scaffold された Yesod サイトであれば、runDB $ do 〜 の中に書くやつです。

PersistStore のメソッド

insert ::  -> m キー

値を挿入して新規発行されたキーを返す

insertKey :: キー ->  -> m ()

値を、キーを指定して挿入する

repsert :: キー ->  -> m ()

キーに対応するエンティティが存在すれば置き換える。でなければ insertKey と同じ

replace :: キー ->  -> m ()

キーに対応するエンティティが存在すれば置き換える。存在しない場合の動作は未定義

delete :: キー -> m ()

指定したキーに対応するエンティティを削除する。存在しなければ何もしない

get :: キー -> m (Maybe )

キーを指定して値を取得する。存在しないかもしれないので Maybe でくるんである。

PersistUnique のメソッド

getBy :: ユニークキー -> m (Maybe エンティティ)

ユニークキーをもとにエンティティを取得する。

deleteBy :: ユニークキー -> m ()

ユニークキーをもとにエンティティを削除する。

insertUnique ::  -> m (Maybe キー)

insert に似ているが、ユニークキー制約を満たさない場合は Nothing を返す

PersistQuery のメソッド

update ::  キー -> 更新内容 -> m ()

指定したキーに対応するエンティティを更新する

updateGet :: キー -> 更新内容 -> m 

update と同時に更新後の値を取得する

updateWhere :: フィルタ -> 更新内容 -> m ()

フィルタに該当するエンティティをすべて更新する

deleteWhere :: フィルタ -> m ()

フィルタに該当するエンティティをすべて削除する。

selectSource :: フィルタ -> オプション -> Source m エンティティ

指定したフィルタとオプションでエンティティを選択し、結果を Source で受け取る(よく知らない)

selectFirst :: フィルタ -> オプション -> m (Maybe エンティティ)

指定したフィルタとオプションで選択された最初のエンティティを Maybe で返す(該当するものがない場合は Nothing)。

selectKeys :: フィルタ -> オプション -> Source m キー

指定したフィルタとオプションでキーを選択し、結果を Source で受け取る

count :: フィルタ -> m Int

フィルタに該当するエンティティの数を Int で返す

その他の関数

insertBy ::  -> m (Either エンティティ キー)

値を挿入するが、ユニークキー制約を満たさない場合、その原因となったエンティティを Left で返す。成功すれば挿入されたエンティティのキーを Right で返す

getJust :: キー -> m 

get に似ているが、キーに対応するエンティティが存在することを想定しているので返り値は Maybe ではない。安全性に欠ける。

belongsTo :: (子の値 -> Maybe 親のキー) -> 子の値 -> m (Maybe 親の値)

一対多の親子関係を形成するエンティティ同士において、親エンティティのキーを Maybe で定義している場合(取得関数を childParentMaybeId とする)に、belongsTo childParentMaybeId child などとして親の値を Maybe で得る

belongsToJust :: (子の値 -> 親のキー) -> 子の値 -> m 親の値

一対多の親子関係を形成するエンティティ同士において、親エンティティのキー取得関数を childParentId とするとき、belongsToJust childParentId child などとして親の値を得る

getByValue ::  -> m (Maybe エンティティ)

指定した値と同等のユニークキー制約を満たすエンティティを一つ取得する。ユニークキーを一つだけもつエンティティで意味を持つ。

checkUnique ::  -> m Bool

指定した値(挿入前の値など)がユニークキー制約にひっかからなければ True を返す。

selectList :: フィルタ -> オプション -> m [エンティティ]

指定したフィルタとオプションでエンティティを選択し、結果を List で受け取る。

deleteCascadeWhere :: フィルタ -> m ()

関連モデルも削除するための機能のようだが、ちょっとわかりません。

Yesod での使用例

makeFormLesson :: Entity Lesson -> Handler FormLesson
makeFormLesson eLesson = do
    let (Entity lessonId lesson) = eLesson
    title <- runDB $ belongsToJust lessonTitleId lesson
    meLessonAttribute <- runDB $ getBy (UniqueAttribute lessonId)
    attributes <- case meLessonAttribute of
            Just eLessonAttribute -> return $
                (,,) <$> lessonAttributePartialAttendable
                     <*> lessonAttributeObservable
                     <*> lessonAttributeExperienceable
                     $ entityVal eLessonAttribute
            Nothing -> do
                let (pa, o, e) = defaultLessonAttributes
                _ <- runDB $ insert $ LessonAttribute lessonId pa o e
                return (pa, o, e)
    return $ FormLesson <$> const title
                        <*> lessonTeacherId
                        <*> lessonSeason
                        <*> lessonSchoolId
                        <*> const attributes
                        <*> lessonDescription
                        <*> lessonPrerequisite
                        $ lesson

FormLessonという型に意味はありませんので気にしないでください。runDBの呼び出しに注目してください 。関連するエンティティをいくつかの方法で取り出しています。

craccho
Work on Ruby, Python, etc. Haskell Lover Cuber Father
https://craccho.hatenadiary.org/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away