11
votes

Haskell and Yesod newbie here. I've been trying to follow the Integration with Yesod example from the Persistent chapter in the Yesod book (http://www.yesodweb.com/book/persistent). The Sqlite compiles and runs fine it seems. However, I'm trying to use MongDB and am having a hard time getting things to work. Specifically:

  1. In the example for sqlite:

    share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persist|

    The Yesod book says "Mongo code will use mongoSettings instead." But I can't find it in any of the modules, and the code doesn't compile. So instead, I had to use this instead of mongoSettings:

    MkPersistSettings { mpsBackend = ConT ''Action }

    I had to import Language.Haskell.TH.Syntax to get it to compile, which I'm assuming should be hidden from the user so I'm certainly not doing it right.

    Also, I found that in the Persistent tests for Mongo do without the "share" and "migrate" part. I'm actually not sure why, I'm guessing it's because MongoDB is Schema-less and doesn't need migration?

  2. SqlPersist

    I thought MongoPersist would be the counterpart to SqlPersist, and I guess it almost is--I found one instance of MongoPersist in the init.hs in the test directory of Persistent. But it's commented out, so I have a feeling it's obsolete? Otherwise it's not defined anyway as far as I can tell. So I don't know how to convert the following line (P.115 of the Yesod book, or near the end of http://www.yesodweb.com/book/persistent) to work for MongoDB:

    instance YesodPersist PersistTest where
        type YesodPersistBackend PersistTest = SqlPersist
        runDB action = do
            PersistTest pool <- getYesod
            runSqlPool action pool
    
  3. Using withMongoDBConn

    So for sqlite, the code is (1st example from the webpage above):

    main :: IO ()
    main = withSqliteConn ":memory:" $ runSqlConn $ do
        runMigration migrateAll
        johnId <- insert $ Person "John Doe" $ Just 35
        ... and so on
    

    But

    main :: IO()
    main = withMongoDBConn ":memory:" $ runMongoDBConn $ do
        runMigration migrateAll 
        johnId <- insert $ Person "John Doe" $ Just 35
        ... and so on          
    

doesn't work. First off, runMigration for some reason isn't in scope. Okay, maybe I don't need migration for MongoDB, so I remove that line. Then, the compiler complains: Couldn't match expected typeAccessMode' with actual type m0 b0' Expected type: m0 t0 -> (t0 -> m0 b0) -> AccessMode Actual type: m0 t0 -> (t0 -> m0 b0) -> m0 b0 and so on. And by this stage my very cursory knowledge of monads just isn't enough to figure this one out.

All in all, I am having a really tough time converting the Integration with Yesod example from the book from Sqlite to MongoDB. Could someone please provide me with a concrete example of Yesod/Persistent with MongoDB? Much thanks in advance.

2
You can use the yesod init scaffolding tool, generate a MongoDB site and see how it's configured. It's difficult to tell exactly which parts are missing from how you've explained your situation.dflemstr
Thanks for the suggestion. Looking through that helps a little bit... though for the most part the resulting code in the directory tree is too complex for me to figure out what's going on. I'll edit the original post to clarify things.Victor

2 Answers

11
votes

I added a page in the Github Yesod Cookbook today that uses MongoDB in conjunction with Persistent. It does not, however, use withMongoDBConn, neither does it avoid TH. Also, I explain there why I use a separate YAML config file. The link: http://bit.ly/VLvmoK

3
votes

I know this is an answer to an old question, but here is a Yesod independent way to get Persistent working with MongoDB. This might be of use to others new to Persistent.

{-# LANGUAGE TemplateHaskell #-}

import Database.Persist 
import Database.Persist.TH
import Database.Persist.MongoDB
import Network (PortID (PortNumber))

let mongoSettings = (mkPersistSettings (ConT ''MongoBackend)) {mpsGeneric = False}
    in share [mkPersist mongoSettings] [persistLowerCase|
Person
    name String
    age Int Maybe
    deriving Show
BlogPost
    title String
    authorId PersonId
    deriving Show
|]
runDBActions actions = 
    withMongoDBConn "myDatabaseName" "localhost" (PortNumber 27017) Nothing 2000 $ \pool ->    
        runMongoDBPool master actions pool

actions = do
    mkey <- insert $ Person "John Doe" $ Just 35
    ...

main :: IO ()
main = do
    runDBactions actions