Daniel K
Daniel K

Reputation: 907

Define and use a Text column as id in persistent mongodb

I'm trying to define and use a table (AKA collection) with a Text column as the unique id. I'm using the 2.0.2 versions of persistent, persistent-mongodb, persistent-template.

This is my table definition:

let mongoSettings = (mkPersistSettings (ConT ''MongoContext)) { mpsGeneric = False }
  in  share [mkPersist mongoSettings, mkMigrate "migrateAll"][persistUpperCase|
User id=myid
  myid     Text
  count    Int
|]

I can't figure out how to create a Key User from a Text value. I attempted:

mkUser :: Text -> Key User
mkUser x = UserKey . MongoKey $ x

with compiler error:

Couldn't match type ‘Text’ with ‘ObjectId’
Expected type: Text -> Key User
  Actual type: ObjectId -> Key User

Are mongo keys in persistent only allowed to be of type ObjectId? From my examination of the relevant source code, this seems to be the case, but I would love to be wrong. Mongodb certainly allows textual keys outside of persistent. In fact, it allows for any unique thing.

I also tried inserting a row like so:

insert $ User "bob" 0

but the resulting database row has an auto-generated ObjectId in the _id column, instead of "bob".

If I define the schema:

User sql=profiles
  _id    Text
  count  Int

then I still have the issue of attempting to define a Key User with a Text value.

Upvotes: 1

Views: 605

Answers (1)

Daniel K
Daniel K

Reputation: 907

This is a new feature in persistent-mongoDB (that was not available when I asked the question), so the answer used to be "No, that's not possible" but is now "Yes, and here is how". It's available as of the 2.0.3 series: persistent-2.0.3, persistent-template-2.0.3, and persistent-mongoDB-2.0.3.

Your schema should have a line: Id <type of _id field> For example:

let mongoSettings = (mkPersistSettings (ConT ''MongoContext)) { mpsGeneric = False }
  in  share [mkPersist mongoSettings][persistUpperCase|
User
  Id   Text
  age  Int
|]

and you insert documents with a specific _id like this:

insertKey (UserKey "alice") $ User 1

Also see the wiki.

Upvotes: 2

Related Questions