Select a subset of Yesod-enabled columns
I am using Persistent with MongoDB. The query selectList
returns the complete list of products and loads them into memory; I would like to return only a subset of the columns.
Q1) Is there a way to select only a subset of the columns so that more data can be loaded. For a more efficient query? Equivalent to mongoDB or SQL projection Possibly SELECT <col,col...>
something like the selectListCols function that also takes a list of attributes as an argument and returns typed column values instead of entity values.
Q2) If not, and I have to resort to Database.MongoDB manual query, what utility can I use from the persistent library to modify the mongodb query generated by selectList so that I can add a mongodb projection to it and get the BSON value
source to share
No, there is no way to do it yet. There is an open question about the permanent github page. The summary is that the authors are waiting until ghc 7.10 does nothing. Link to open issue and closed duplicate .
You can use a raw driver to implement your requests. For the mongoDB library see Database.MongoDB.Query.Projector. In a closed ticket, gregwebs suggests "There are many helpers in persistent-mongoDB now for leveraging some persistent type safety with a raw driver (the field name will definitely be your friend for predictions)"
I don't know how to change the query generated by the selectList to do the projection. I doubt there is a way to do this with the current API, but I'm sure you can do it with the fixed constant.
Here's another workaround: do you think you are specifying different PersistEntity
but keeping the collection name the same? For example.
let mongoSettings = (mkPersistSettings (ConT ''MongoBackend)) { mpsGeneric = False }
in share [mkPersist mongoSettings, mkMigrate "migrateAll"][persistUpperCase|
Thing sql=thing_collection
name String
stuff [Int32]
deriving Show
SmallThing sql=thing_collection
name String
deriving Show
|]
Note what is sql=thing_collection
used to force the PersistEntity to reference the same MongoDB collection.
There are some tradeoffs in this workaround:
Pros:
- It was clear in the type system which fields would be returned from the query. The query returning
SmallThing
obviously does not containstuff
. It makes a compile-time error to make the request and omit the field you want to read later.
Minuses:
- You will need to define
PersistEntity
for each option. This can be many options if you have documents with many fields and are trying to squeeze every last performance out of your queries. - You must sync the options.
- Conversion. How do you "downgrade"
Thing
toSmallThing
type safe, no templates? For example. you haveThing
and you are calling the function expectingSmallThing
.
You can use fromJSON
and toJSON
, but aeson doesn't support ByteString
s, so JSON won't be useful if you have ByteString
s.
Also check toPersistFields
and fromPersistFields
. Perhaps they can be used instead of JSON.
source to share