ReactiveMongo 学习笔记

来源:互联网 发布:java常用设计模式详解 编辑:程序博客网 时间:2024/06/01 09:47

ReactiveMongo 学习笔记

ReactiveMongo是scala的mongodb驱动,提供了完全非阻塞和异步i/o操作。
同样是由于上一个网游服务器用到,在网上查找发现资料不多,中文资料更少。所以做个笔记,方便以后查阅也可以和朋友探讨相关问题。
没有太多的解释,下面是一个完整的Demo代码,伴有注释
官网: http://reactivemongo.org
API和Samples: http://reactivemongo.org/documentation.html


  • 先介绍下环境搭建

1.使用IntelliJ IDEA下载scala和sbt插件
2.用sbt创建一个scala项目,然后在build.sbt中使用如下配置

name := "RMongo"version := "1.0"scalaVersion := "2.10.4"resolvers += "Sonatype Snapshots" at "http://repo.typesafe.com/typesafe/releases/"libraryDependencies ++= Seq(  "org.reactivemongo" %% "play2-reactivemongo" % "0.10.0",  "joda-time" % "joda-time" % "2.2" //这是一个用来处理时间的第三方包)
  • 代码如下,分增删改查四个部分
import org.joda.time.DateTimeimport reactivemongo.api.MongoDriverimport reactivemongo.bson._import reactivemongo.bson.buffer.BSONIteratorimport reactivemongo.core.commands.RawCommandimport scala.concurrent.ExecutionContext.Implicits.globalclass RMongoStudy {  // 获得mongo driver实例(creates an actor system)  val driver = new MongoDriver()  val connection = driver.connection(List("localhost"))// 参数是一个节点名称List, 例如"node1.foo.com:27017", 端口号是可选的,默认是27017.  // 获得数据库"mygame"的引用  val db = connection("mygame")//参数是db name, 执行插入或更新操作时若不存在会自动创建  // 获得collection"players"的引用,默认是一个BSONCollection  val playerCollection = db("players")  //参数是collection(table) name, 执行插入或更新操作时若不存在会自动创建  //增  def createTest() : Unit= {    //创建一个新的文档,用来插入    val newPlayerDoc = BSONDocument(      "_id" -> BSONObjectID.generate,   //ID类型      "createTime" -> BSONDateTime(DateTime.now.getMillis),//时间类型      "clientVersion" -> "1.0.0",       //字符串类型      "channel" -> "000255",      "state" -> BSONDocument(          //state是个内嵌文档        "name" -> "Libai1",        "gold" -> 1000                  //整数类型      )    )    //插入函数只有一个参数,返回一个Future[LastError]类型的结果,map是用来提取Future变量类型中的数据    //具体函数定义请参考API中的BSONCollection  insert    playerCollection.insert(newPlayerDoc) map { result =>      println("create doc "+result.ok)    }  }  //删  def deleteTest() : Unit= {    //创建一个新的文档,用来指定删除条件    val query = BSONDocument("state.name"->"Libai1")    //第二个参数是可选的,默认为false,具具体函数定义请参考API中的BSONCollection remove    playerCollection.remove(query,firstMatchOnly=true) map { result =>      println("delete doc "+result.ok)    }  }  //改  def updateTest() : Unit= {    //更改条件    val selector = BSONDocument("state.name"->"Libai")    //更改内容   更新内嵌文档,整数、增加 $inc比$set要高效    val updateGold = BSONDocument("$inc"->BSONDocument("state.gold"->500))    //更新指定字段内容,若无“$set”,则代表将原文档替换、替换、替换(重要的事情要说三变)成此文档,这个地方要加以小心,替换的话,新文档没有的字段都会删掉    val updateVersion = BSONDocument("$set"->BSONDocument("clientVersion"->"1.2.0"))    //upsert的意思是“若无则创建”,multid的意思是“批量”,具具体函数定义请参考API中的BSONCollection update    //playerCollection.update(selector,updateGold,upsert=true,multi=false) map { result =>    //  println("update doc "+result.ok)    //}    playerCollection.update(selector,updateVersion,upsert=true,multi=false) map { result =>      println("update doc "+result.ok)    }  }  //查  def findTest() : Unit= {//    val selector = BSONDocument("state.name"->"Libai")////    //普通查询  将查询的结果转换成一个Future[List[BSONDocument]()]//    //find有两个参数,第一个参数是条件。第二个参数是可选的,projection(投影或映射)意思是查询结果中只保留哪些字段,不填的话是全部保留//    //collect[List](n) n是一个可选的整数,代表保留前n条数据,不填是查询结果全保留//    playerCollection.find(selector).cursor[BSONDocument].collect[List]() map { resultDocList =>//      println("the data are:")//      for(doc <- resultDocList){                                            //用for取出Future的值//        val id = doc.getAs[BSONObjectID]("_id").getOrElse(BSONObjectID)     //获取"_id"//        val clientVersion = doc.getAs[BSONString]("clientVersion").getOrElse(BSONString("no version")).value //        val stateDoc = doc.getAs[BSONDocument]("state").getOrElse(BSONDocument()) //获取内嵌文档//        val name = stateDoc.getAs[BSONString]("name").getOrElse(BSONString("no name")).value //获取内嵌文档内字段的值//        val gold = stateDoc.getAs[BSONInteger]("gold").getOrElse(BSONInteger(0)).value////        println("_id:"+id+",clientVersion:"+clientVersion+",name:"+name+",gold:"+gold)//      }//    }/**   getAs[BSONString](“name”).getOrElse(BSONString(“unknown”)).value *     也可以写成*     getAs[String](“name”).getOrElse(“unknown”)    **/    Int Boolean等都类似    //聚合查询    //    假设有如下数据每个channel下有3个玩家,我想查询每个channel下的玩家gold之和是多少。//    { "_id" : ..., "createTime" : ..., "clientVersion" : "1.0.0", "channel" : "000255", "state" : { "name" : "Libai1", "gold" : 1000 } }//    { "_id" : ..., "createTime" : ..., "clientVersion" : "1.0.0", "channel" : "000255", "state" : { "name" : "Libai2", "gold" : 2000 } }//    { "_id" : ..., "createTime" : ..., "clientVersion" : "1.0.0", "channel" : "000255", "state" : { "name" : "Libai3", "gold" : 3000 } }//    { "_id" : ..., "createTime" : ..., "clientVersion" : "1.0.0", "channel" : "100120", "state" : { "name" : "Baijuyi1", "gold" : 1500 } }//    { "_id" : ..., "createTime" : ..., "clientVersion" : "1.0.0", "channel" : "100120", "state" : { "name" : "Baijuyi2", "gold" : 2500 } }//    { "_id" : ..., "createTime" : ..., "clientVersion" : "1.0.0", "channel" : "100120", "state" : { "name" : "Baijuyi3", "gold" : 3500 } }//    { "_id" : ..., "createTime" : ..., "clientVersion" : "1.0.0", "channel" : "000066", "state" : { "name" : "Wanganshi1", "gold" : 1200 } }//    { "_id" : ..., "createTime" : ..., "clientVersion" : "1.0.0", "channel" : "000066", "state" : { "name" : "Wanganshi2", "gold" : 2200 } }//    { "_id" : ..., "createTime" : ..., "clientVersion" : "1.0.0", "channel" : "000066", "state" : { "name" : "Wanganshi3", "gold" : 3200 } }    //$group,$sort,$limit,$sum都是聚合关键字,_id是ID关键字 这些都不能变。amount是自己取得名字,将后面$sum的结果赋值给这个变量    //注意下面那些地方用到了$,$,$(重要的事情要说三遍)符号    val commondDoc = BSONDocument(      "aggregate" -> "players",      "pipeline"  -> BSONArray(        BSONDocument("$group" -> BSONDocument("_id"->"$channel","amount"->BSONDocument("$sum"->"$state.gold"))),  //分组         BSONDocument("$sort"  -> BSONDocument("amount" -> -1)), //排序        BSONDocument("$limit" -> 3) //选取特定数量的返回值      )    )    val resultFuture = db.command(RawCommand(commondDoc))//默认返回 Future[BSONDocument]    //BSONDocument里存放一个以“result”(就是result这个名字,不是我自己起的)命名BSONArray来保存聚合查询的数据    for(result <- resultFuture){      val rankArray = result.getAs[BSONArray]("result").getOrElse(BSONArray())      for(i<-0 until rankArray.length){        val record = rankArray.getAs[BSONDocument](i).getOrElse(BSONDocument())        val channel = record.getAs[String]("_id").getOrElse("no channel")         val amount = record.getAs[Int]("amount").getOrElse(0) //这个"amount"变量名,要和创建doc时,分组中的那个”amount“保持一致        println("channel:"+channel+",amount:"+amount)      }    }  }}object RMongoStudy{  def main (args: Array[String]) {    val mongo = new RMongoStudy()//    mongo.createTest()//    mongo.deleteTest()//    mongo.updateTest()    mongo.findTest()  }}
0 0
原创粉丝点击