Haskell中如何将自定义数据类型转换为BSON Document?
我完全懂你在Data.Bson.Mapping上卡壳的感觉——这个包的文档确实有点过于简洁,尤其是自定义类型和Document互转这块,示例少得可怜。让我结合你的场景,一步步拆解解决方法:
第一步:先搞定自定义类型的Mapping实例
要让自定义类型能转换成Document,核心是为它实现Mapping类型类。最便捷的方式是用Template Haskell的deriveMapping自动生成实例,比如先定义你的类型:
{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE DeriveGeneric #-} import Data.Bson.Mapping import Data.Text (Text) import Database.MongoDB (ObjectId) -- 你的自定义类型 data User = User { userId :: ObjectId , userName :: Text , userAge :: Int } deriving (Show, Eq, Generic) -- 自动生成Mapping实例 deriveMapping ''User
如果需要手动控制字段名(比如把Haskell的驼峰名转成MongoDB的下划线名),也可以手动写Mapping实例:
instance Mapping User where toDoc (User uid name age) = [ "user_id" =: uid , "user_name" =: name , "user_age" =: age ] fromDoc doc = User <$> doc ! "user_id" <*> doc ! "user_name" <*> doc ! "user_age"
第二步:把自定义类型转成Document
有了Mapping实例后,直接用toDocument函数就能完成转换,这才是你要的核心操作:
sampleUser :: User sampleUser = User (ObjectId "60d21b4667d0d8992e610c85") "Lou Süsslin" 28 -- 转换为Document userDocument :: Document userDocument = toDocument sampleUser
关于你提到的
selectFields:别搞混场景! 你说尝试用selectFields但不知道怎么把Expression (Q Exp)转成Document——这里的关键是:selectFields不是用来做类型转Document的,它是用来**构建MongoDB查询的投影(Projection)**的,也就是指定查询时只返回哪些字段。
要把它的结果转换成实际的Document,需要结合mkProjection和Template Haskell的拼接语法$(...)(因为selectFields返回的是编译时表达式):
import Database.MongoDB (Query(..), select, project) -- 生成只返回userName和userAge的投影Document userProjection :: Document userProjection = $(mkProjection $ selectFields ''User ["userName", "userAge"]) -- 用这个投影构建查询 userQuery :: Query userQuery = select [] "users" { project = userProjection }
总结一下
- 先为自定义类型生成/编写
Mapping实例,这是转换的基础 - 用
toDocument直接把类型实例转成Document(这是你最初要的功能) selectFields是查询投影工具,需要配合Template Haskell拼接才能得到实际的Document
内容的提问来源于stack exchange,提问作者Lou Süsslin
相关产品推荐
相关产品推荐

