Mongo Scala Driver Collection Does Not Update Document - mongodb

I'm able to insert, read, and delete but I cannot get either updateOne or updateMany to modify documents.
I'm using MongoDB 3.2.7 with libraryDependencies += "org.mongodb.scala" %% "mongo-scala-driver" % "1.1.1"
def read() = {
val query = Document("title" -> "Text Tiling")
methods.find(query).subscribe(
(method: Document) => update(method.toJson()), // onNext
(error: Throwable) => Logger.debug(s"Query failed: ${error.getMessage}"), // onError
() => Logger.debug("onComplete") // onComplete
)}
def update(jsonSting:String): Unit = {
Logger.debug("update() " + jsonSting)
Logger.debug(methods.find().first().toString)
val observer = new Observer[UpdateResult] {
override def onSubscribe(subscription: Subscription): Unit = {
Logger.debug("onSubscribe: " + subscription.toString)
}
override def onComplete: Unit = {
Logger.debug("onComplete")
}
override def onError(e: Throwable): Unit = {
Logger.debug("onError: " + e.getMessage)
}
override def onNext(doc: UpdateResult) {
Logger.debug("onNext")
}
}
val filter = Document("title" -> "Text Tiling")
val mod = Document("$set" -> Document("reputation" -> 5))
val result = methods.updateOne(filter,mod).subscribe(observer)
Logger.debug("result: " + result)}
Here are the logs:
[debug] application - update() { "_id" : { "$oid" : "5759542a4e0bf602adcab149" }, "title" : "Text Tiling", "reputation" : 0 }
[debug] application - org.mongodb.scala.ObservableImplicits$BoxedObservable#61ddc581
[debug] application - onSubscribe: org.mongodb.scala.ObservableImplicits$BoxedSubscription#6252b659
[debug] application - result: ()
[debug] application - onComplete

Calling request on the subscription worked for me. The other events were then called after.
override def onSubscribe(subscription: Subscription): Unit = {
subscription.request(1)
}
[debug] application - onNext
[debug] application - onComplete!

val filter : Bson = new Document(“key”, “old_value”)
val newValue : Bson = new Document(“key” ,”new_value”)
val updateOperationDocument : Bson = new Document("$set", newValue)
val collection = db.getCollection(“collection_name”)
collection.updateOne(filter, updateOperationDocument)

Related

Download an archive file on the fly using play framework 2.3

I'am trying to create and download an archive file without relying on memory(to avoid out of memory exception for large file) I'am using for that play framework 2.3 with Scala, after some research I found an example: https://gist.github.com/kirked/412b5156f94419e71ce4a84ec1d54761, I made some modification on it. My problem is when I download the file and try to open it I get this exception: An error occurred while loading the archive.
here all the code:
def zip() = Action {
implicit request: Request[AnyContent] =>
val buffer = new ZipBuffer(10000)
val writeCentralDirectory = Enumerator.generateM(Future{
if (buffer.isClosed) {
None
}
else {
buffer.flush
buffer.close
Some(buffer.bytes)
}
})
val test = Enumerator.apply(ResolvedSource2("test.txt", "helllo"))
Ok.chunked(test &> zipeach2(buffer) andThen writeCentralDirectory >>> Enumerator.eof) as withCharset("application/zip") withHeaders(
CONTENT_DISPOSITION -> s"attachment; filename=aa.zip")
}
case class ResolvedSource2(filepath: String, stream: String)
def zipeach2(buffer: ZipBuffer)(implicit ec: ExecutionContext): Enumeratee[ResolvedSource2, Array[Byte]] = {
Enumeratee.mapConcat[ResolvedSource2] { source =>
buffer.zipStream.putNextEntry(new ZipEntry(source.filepath))
var done = false
def entryDone: Unit = {
done = true
buffer.zipStream.closeEntry
}
def restOfStream: Stream[Array[Byte]] = {
if (done) Stream.empty
else {
while (!done && !buffer.full) {
try {
val byte = source.stream
buffer.zipStream.write(byte.getBytes)
entryDone
}
catch {
case e: IOException =>
println(s"reading/zipping stream [${source.filepath}]", e)
}
}
buffer.bytes #:: restOfStream
}
}
restOfStream
}
}
}
class ZipBuffer(capacity: Int) {
private val buf = new ByteArrayOutputStream(capacity)
private var closed = false
val zipStream = new ZipOutputStream(buf)
def close(): Unit = {
if (!closed) {
closed = true
reset
zipStream.finish()
zipStream.close // writes central directory
}
}
def flush() = {
zipStream.flush()
}
def isClosed = closed
def reset: Unit = buf.reset
def full: Boolean = buf.size >= capacity
def bytes: Array[Byte] = {
val result = buf.toByteArray
reset
result
}
}

mongodb with scala maven project

I am stuck on an issue. I have created a scala maven project where I am trying to communicate with mongo. My project is getting build successfuly and I do not get any error when I execute my project, but still no data is getting inserted in my mongodb.
If I insert data manually through mongo-cli then my code can read it but it is not even inserting a single record.
Could you please help me in finding where I am making mistakes.
My mongo version is 3.2.10
App.scala
package com.assignment.scala
import org.mongodb.scala._
import org.mongodb.scala.model.Aggregates._
import org.mongodb.scala.model.Filters._
import org.mongodb.scala.model.Projections._
import org.mongodb.scala.model.Sorts._
import org.mongodb.scala.model.Updates._
import org.mongodb.scala.model._
/**
* #author ${user.name}
*/
object App {
def main(args: Array[String]) {
println("Calling insertDoc==")
insertDoc()
}
def insertDoc() = {
val mongoClient = MongoClient()
val database = mongoClient.getDatabase("assignment")
val collection = database.getCollection("links")
println("collection find : " + collection.find())
collection.find().subscribe(
(user: Document) => println("document------------"+user.toJson()),
(error: Throwable) => println(s"Query failed: ${error.getMessage}"),
() => println("Done"))
collection.drop()
val bufferedSource = io.Source.fromFile("/home/impadmin/ServiceSource/ml-latest-small/links.csv")
var firstLine = List[String]();
var docList = List[Document]();
for ((line,count) <- bufferedSource.getLines.zipWithIndex) {
val cols = line.split(",").map(_.trim)
if (firstLine.size <= 0 && cols.length > 0) {
firstLine = cols.toList;
} else {
var doc: Document = Document("_id" -> count)
for ((a, b) <- firstLine zip cols) {
doc ++= Document(a -> b)
}
docList = docList :+ doc
collection.insertOne(doc)
}
}
val doc3 = Document("name" -> "MongoDB", "type" -> "database",
"count" -> 1, "info" -> Document("x" -> 203, "y" -> 102))
collection.insertOne(doc)
collection.find().subscribe((doc1: Document) => println(doc1.toJson()),
(e: Throwable) => println(s"There was an error: $e"))
}
}
It worked using subscribe:
val insertObservable1: Observable[Completed] = collection.insertMany(docList);
val latch1 = new CountDownLatch(1)
insertObservable1.subscribe(new Observer[Completed] {
override def onError(e: Throwable): Unit = {
println("Error1")
e.printStackTrace()
}
override def onSubscribe(subscription: Subscription): Unit = {
subscription.request(java.lang.Long.MAX_VALUE)
println("inserting1-------------")
}
override def onComplete(): Unit = {
println("Completed1")
latch1.countDown()
}
override def onNext(result: Completed): Unit = {
println("Next1-----------")
}
})
latch1.await()
}
})

IllegalArgumentException: Invalid BSON field name uuid

So I've tried seemingly countless things to get this to work. When I call queueWrite, the println statements give me this:
{ "uuid" : "49f2-0b64-4bf3-49f2a35b-bbe8-4954f742d88b" }
and this:
{ "uuid" : "49f2-0b64-4bf3-49f2a35b-bbe8-4954f742d88b", "name" : "personName", "key" : "3E6A" }
Which (I'm pretty sure) is just fine. However, after it prints, I get this:
java.lang.IllegalArgumentException: Invalid BSON field name uuid
Afaik, the field name uuid is fine, the only things about an improper name I could really find is to just make sure there are no '.' symbols in it (which there aren't)
def queueWrite(collection: String, filter: Map[String, () => String], data: Map[String, () => String]) {
val col = collections.get(collection).get
val filterDoc = new BsonDocument
filter.foreach(f => { filterDoc append (f._1, new BsonString(f._2.apply)) })
val filterBson = Document(filterDoc)
println("filter: \n" + filterBson.toJson)
val dataDoc = new BsonDocument
data.foreach(f => { dataDoc append (f._1, new BsonString(f._2.apply)) })
val dataBson = Document(dataDoc)
println("data: \n" + dataBson.toJson)
val options = new FindOneAndUpdateOptions
options.returnDocument(ReturnDocument.AFTER)
options.upsert(true)
val observer = new Observer[Document] {
override def onSubscribe(s: Subscription) = s.request(1)
override def onNext(doc: Document) = println(doc.toJson)
override def onError(e: Throwable) = e.printStackTrace
override def onComplete = println("onComplete")
}
val observable: Observable[Document] = col.findOneAndUpdate(filterBson, dataBson, options)
observable.subscribe(observer)
}
Any ideas / suggestions are greatly appreciated as always :)

Testing reactivemongo with scalatest raise an exception

I am trying to test some functionality in the app. I have other tests (with scalatest for reactivemongo) and are working, but with this I am getting this exception
[info] - should Persist and find a token * FAILED *
[info] The future returned an exception of type: reactivemongo.api.commands.bson.DefaultBSONCommandError, with message: CommandError[code=26, errmsg=ns not found, doc: {
[info] ok: BSONDouble(0.0),
[info] errmsg: "ns not found",
[info] code: BSONInteger(26)
[info] }]. (DaosApplicationSpecOneAppPerTest.scala:74)
This is the code for the tests (both are throwing the same error)
class UserTokenDaoMongoSpec extends DaosApplicationSpecOneAppPerTest {
"UserTokenDao" should {
"Persist and find a token" in withUserTokenDao { userTokenDao =>
val future = for {
_ <- userTokenDao.save(token)
maybeToken <- userTokenDao.find(token.id)
} yield {
maybeToken.map(_ == token)
}
whenReady (future) { result =>
result.get must be (true)
}
}
"Remove a token" in withUserTokenDao { userTokenDao =>
val future = for {
_ <- userTokenDao.save(token)
_ <- userTokenDao.remove(token.id)
maybeToken <- userTokenDao.find(token.id)
} yield {
maybeToken
}
whenReady (future) { result =>
result must be (None)
}
}
}
}
and for brevity, this is the method that inherits
def withUserTokenDao[T](t: UserTokenDao => T):T = running(app) {
val userTokenDao = new UserTokenDaoMongo
whenReady (userTokenDao.tokens.drop()) { result =>
t(userTokenDao)
}
}
The UserTokenDao implementation
class UserTokenDaoMongo extends UserTokenDao {
lazy val reactiveMongoApi = current.injector.instanceOf[ReactiveMongoApi]
val tokens = reactiveMongoApi.db.collection[JSONCollection]("tokens")
def find(id:UUID):Future[Option[UserToken]] =
tokens.find(Json.obj("id" -> id)).one[UserToken]
def save(token:UserToken):Future[UserToken] = for {
_ <- tokens.insert(token)
} yield token
def remove(id:UUID):Future[Unit] = for {
_ <- tokens.remove(Json.obj("id" -> id))
} yield ()
}
and this is the model of UserToken
class UserTokenDaoMongo extends UserTokenDao {
lazy val reactiveMongoApi = current.injector.instanceOf[ReactiveMongoApi]
val tokens = reactiveMongoApi.db.collection[JSONCollection]("tokens")
def find(id:UUID):Future[Option[UserToken]] =
tokens.find(Json.obj("id" -> id)).one[UserToken]
def save(token:UserToken):Future[UserToken] = for {
_ <- tokens.insert(token)
} yield token
def remove(id:UUID):Future[Unit] = for {
_ <- tokens.remove(Json.obj("id" -> id))
} yield ()
}
I am not sure what could be causing the error
Thank you
It turned out that the problem was that the collection tokens did not exist. I got into the mongo console, then I created the collection and the tests started working.

How to test MongoDB connection?

How do I test a MongoDB connection? Here is my code:
class MongoDB(val SERVER:String, val PORT:Int, val DATABASE: String, val COLLECTION: String){
def establishConnection(): MongoCollection = {
val mongoClient = MongoClient(SERVER, PORT)
println("MongoDB client connection: "+ mongoClient)
val db_handle = mongoClient(DATABASE)
println("Connected to DB : "+ DATABASE)
println("Collections present are :")
println(db_handle.collectionNames)
assert (establishConnection.size > 0 )
db_handle(COLLECTION)
}
def insert(collection : MongoCollection, document : MongoDBObject) : Unit = {
println(collection.insert(document))
}
def find(collection : MongoCollection) = {
println("In find query() :")
val cursor = collection.find()
cursor.toList
}
def find(collection : MongoCollection, obj : MongoDBObject) = {
println("In find query() with condition:")
val cursor = collection.find(obj)
cursor.toList
}
def findOne(collection : MongoCollection) ={
println("In findOne query() :")
val cursor = collection.findOne()
cursor.toList
}
def findOne(collection: MongoCollection, obj : MongoDBObject) ={
println("In findOne query() with condition:")
val cursor = collection.findOne(obj)
cursor.toList
}
def update(collection : MongoCollection, query : MongoDBObject, update : MongoDBObject) = {
val result = collection.update(query, update) //update or findAndModify can be used
result
}
def delete(collection : MongoCollection, query : MongoDBObject) = {
val result = collection.findAndRemove(query);
result
}
}
You can use embedded mongo it's written in java, it first downloads mongo and stores it in home directory ( it downloads only for very first time) and then runs it, you can choose mongoDB version, here is a sample project how to use it from scala test https://github.com/SimplyScala/scalatest-embedmongo.