Play-Mongo 简洁易用的 Play Framework MongoDB 模块开源项目

我要开发同款
匿名用户2018年06月10日
114阅读

技术信息

开源地址
https://gitee.com/joymufeng/play-mongo
授权协议
Apache

作品详情

play-mogo介绍

play-mogo是一个专门为 PlayFramework 开发的Mogodb模块,旨在为PlayFramework提供一种简洁的Mogodb访问方式。该项目基于Mogodb官方的 MogodbScalaDriver 开发,并且提供了更多实用功能,例如,

更简洁多样的数据库交方式

自动识别模型类(Model),自动编解码

自动完成JsValue和BsoValue互转

更方便的GridFS交互

ChageStream转AkkaStream.

支持关联查询(RelatioshipQuery)

GettigStarted

打开build.sbt,添加如下依赖,

libraryDepedecies += "c.playscala" % "play-mogo_2.12" % "0.1.0"

打开 cof/applicatio.cof,添加数据库连接,

mogodb.uri = "mogodb://user:password@host:port/play-commuity?authMode=scram-sha1"

然后需要配置 Model 位置,配置代码需要在应用启动之前执行,

Mogo.setModelsPackage("models")

建议将上述代码放置在顶层包路径下的默认 Module 类中,

class Module exteds AbstractModule {  override def cofigure() = {    Mogo.setModelsPackage("models")    bid(classOf[IitializeService]).asEagerSigleto  }}

至此便可以将 Mogo 实例注入到任意需要的地方,

@Sigletoclass Applicatio @Iject()(cc: CotrollerCompoets, mogo: Mogo) exteds AbstractCotroller(cc) {}ModeladCollectio

Model类使用 @Etity 注解标注,一个model实例表示mogodbcollectio中的一个文档,一个mogodbcollectio在概念上类似于关系数据库的一张表。

@Etity("commo-user")case class User(_id: Strig, ame: Strig, password: Strig, addTime: Istat)

@Etity 注解参数用于指定关联的mogodbcollectio名称,如果未指定,则默认为Model类名称。作为约定,Model类使用 _id 字段作为唯一标识,该字段同时也是mogodbcollectio的默认主键。

我们可以通过两种方式访问mogodbcollectio,第一种方式是使用model类,

mogo.fid[User]().list().map{ users => ... }

这里的参数类型 User 不仅用于指定关联的mogodbcollectio,而且用于指明返回的结果类型。这意味着查询操作将会在 commo-user collectio上执行,并且返回的结果类型是 User。需要注意的是,在该方式下无法改变返回的结果类型。

第二种方式是使用 mogo.getCollectio 方法,

mogo.collectio("commo-user").fid[User]().list().map{ user => }

在这里, fid 方法上的参数类型 User 仅仅用于指定返回的结果类型,我们可以通过更改该参数类型设置不同的返回结果类型,

mogo.collectio("commo-user").fid[JsObject]().list().map{ jsObjList => }mogo.collectio("commo-user").fid[CommoUser](Jso.obj("userType" -> "commo")).list().map{ commoUsers => }

当然,我们也可以使用model类指定关联的mogodbcollectio,

mogo.collectio[User].fid[User]().list().map{ user => }

第1个参数类型 User 用于指定关联的mogodbcollectio,第2个参数类型 User 用于指定返回的结果类型。我们仍然可以通过改变第2个参数类型从而改变返回的结果类型。

常用操作

以下示例代码默认执行了 importplay.api.libs.jso.Jso._ 导入,所以 Jso.obj() 可以被简写为 obj() 。

Create// 插入 Modelmogo.isert[User](User("0", "joymufeg", "123456", Istat.ow))// 插入 Jsoval jsObj = obj("_id" -> "0", "ame" -> "joymufeg", "password" -> "123456", "addTime" -> Istat.ow)mogo.collectio[User].isert(jsObj)mogo.collectio("commo-user").isert(jsObj)Updatemogo.updateById[User]("0", obj("$set" -> obj("password" -> "123321")))mogo.updateOe[User](obj("_id" -> "0"), obj("$set" -> obj("password" -> "123321")))mogo.collectio[User].updateById("0", obj("$set" -> obj("password" -> "123321")))mogo.collectio[User].updateOe(obj("_id" -> "0"), obj("$set" -> obj("password" -> "123321")))mogo.collectio("commo-user").updateById("0", obj("$set" -> obj("password" -> "123321")))mogo.collectio("commo-user").updateOe(obj("_id" -> "0"), obj("$set" -> obj("password" -> "123321")))Querymogo.fidById[User]("0") // Future[Optio[User]]mogo.fid[User](obj("_id" -> "0")).first // Future[Optio[User]]mogo.collectio[User].fidById[User]("0") // Future[Optio[User]]mogo.collectio[User].fid[User](obj("_id" -> "0")).first // Future[Optio[User]]mogo.collectio[User].fidById[JsObject]("0") // Future[Optio[JsObject]]mogo.collectio[User].fid[JsObject](obj("_id" -> "0")).first // Future[Optio[JsObject]]mogo.collectio("commo-user").fidById[User]("0") // Future[Optio[User]]mogo.collectio("commo-user").fid[User](obj("_id" -> "0")).first // Future[Optio[User]]mogo.collectio("commo-user").fidById[JsObject]("0") // Future[Optio[JsObject]]mogo.collectio("commo-user").fid[JsObject](obj("_id" -> "0")).first // Future[Optio[JsObject]]Deletemogo.deleteById[User]("0")mogo.deleteOe[User](obj("_id" -> "0"))mogo.collectio[User].deleteById("0")mogo.collectio[User].deleteOe(obj("_id" -> "0"))mogo.collectio("commo-user").deleteById("0")mogo.collectio("commo-user").deleteOe(obj("_id" -> "0"))UploadadDowloadFiles// Upload ad get the fileIdmogo.gridFSBucket.uploadFromFile("image.jpg", "image/jpg", ew File("./image.jpg")).map{ fileId =>  Ok(fileId)}// Dowload file by fileIdmogo.gridFSBucket.fidById("5b1183fed3ba643a3826325f").map{  case Some(file) =>    Ok.chuked(file.stream.toSource)      .as(file.getCotetType)  case Noe =>    NotFoud}ChageStream

我们可以通过 toSource 方法将ChageStream转换成AkkaSource,之后便会有趣很多。例如下面的代码拥有如下几个功能:

将从ChageStream接收到的元素进行缓冲,以方便批处理,当满足其中一个条件时便结束缓冲向后传递:

缓冲满10个元素

缓冲时间超过了1000毫秒

对缓冲后的元素进行流控,每秒只允许通过1个元素

mogo  .collectio[User]  .watch()  .fullDocumet  .toSource  .groupedWithi(10, 1000.millis)  .throttle(elemets = 1, per = 1.secod, maximumBurst = 1, ThrottleMode.shapig)  .ruForeach{ seq =>     // ...  }RelatioshipQuery@Etity("commo-article")case class Article(_id: Strig, title: Strig, cotet: Strig, authorId: Strig)@Etity("commo-author")case class Author(_id: Strig, ame: Strig)mogo.fid[Article].fetch[Author]("authorId").list().map{ _.map{ t =>    val (article, author) = t  }}

对于满足查询条件的每一个article,将会根据匹配条件 article.authorId==author._id 拉取关联的author。

Class,Jso和Bso

在处理Jso时要格外小心,因为Jso使用 JsNumber 表示所有数值类型,但是Bso拥有更加丰富的数值类型,这导致了Jso和Bso之间的转换过程是不可逆的,因为双方的类型信息并不对称。下面我们仔细分析常见的几个场景。在讨论中将会用到如下的Model定义:

@Etity("commo-user")case class User(_id: Strig, ame: Strig, settig: UserSettig)case class UserSettig(geder: Strig, age: It)Class->Bso

我们经常使用下面代码将一个Model类实例插入mogodb,

mogo.isert[User].isert(User("0", "joymufeg", UserSettig("male", 32)))

在调用底层驱动的插入操作之前,需要先将 User 转换成 Bso 。这个转换过程是可逆的,当从mogodb读取数据时,可以成功地将 Bso 转换回 User。

Jso->Bso

当使用JsoDSL构建一个 JsObject 对象时,所有的数值类型(例如Byte,Short,It,Log,Float和Double)均会被转换成 JsNumber 类型(内部使用BigDecimal存储数据),数值的具体类型在这个转换过程中丢失了。在调用底层驱动程序前,Jso 将会被转换为 Bso,JsNumber 将会被转换为 BsoDecimal128。当从数据库读取写入的数据时,我们没办法恢复已经丢失的数值类型信息。例如我们通常会执行如下更新操作,

mogo.update[User](Jso.obj("_id" -> "0"), Jso.obj("$set" -> UserSettig("male", 18)))// Ormogo.update[User](Jso.obj("_id" -> "0"), Jso.obj("$set" -> Jso.obj("settig" -> Jso.obj("geder" -> "male", "age" -> 18))))

不管是 UserSettig("male",32),还是 Jso.obj("geder"->"male","age"->18) 最终都会被转换为 Jso.obj("geder"->JsStrig("male"),"age"->JsNumber(BigDecimal(18))。所以,在更新操作执行完成后, user.settig.age 字段在数据库中的类型为 NumberDecimal,当执行读取操作时便会发生类型转换错误,

mogo.fidById[User]("0")// [BsoIvalidOperatioExceptio: Ivalid umeric type, foud: DECIMAL128]

当试图将 BigDecimal 转换为 It 时出错了.因为在这个转换过程中会导致数值精度丢失。为了解决这个问题,我们在转换 JsNumber 时尽量将其转换为较窄的数值类型,以保证其可以被安全地转换回来。例如 Jso.obj("age"->JsNumber(18.0))会被转换为 BsoDocumet("age",BsoIt32(18))。

功能介绍

play-mongo 介绍 play-mongo 是一个专门为 Play Framework 开发的 Mongodb 模块, 旨在为 Play Framework 提供一种简洁的 Mongodb...

声明:本文仅代表作者观点,不代表本站立场。如果侵犯到您的合法权益,请联系我们删除侵权资源!如果遇到资源链接失效,请您通过评论或工单的方式通知管理员。未经允许,不得转载,本站所有资源文章禁止商业使用运营!
下载安装【程序员客栈】APP
实时对接需求、及时收发消息、丰富的开放项目需求、随时随地查看项目状态

评论