Get ID after insert with ReactiveMongo
Asked Answered
C

2

6

I'm writing a web service with akka-http and ReactiveMongo. I faced with problem, which I unable to resolve by myself.

I have method

 def saveRoute(route: Route)(implicit writer: BSONDocumentWriter[Route]): Future[WriteResult] = {
    collection.insert(route)
  }

The problem is WriteResult doesn't contain any useful information except error or OK status.

Could you please explain how to get inserted object ID after insert. All examples which I've found are either related to old version with LastError or with Play! Framework.

Calorific answered 6/9, 2016 at 16:12 Comment(0)
C
1

I managed to get ID or any other field, or even entire object by returning tuple from save method.

def saveRoute(route: Route)(implicit writer: BSONDocumentWriter[Route]) = {
    collection.insert(route).map((_, route))
  }

I copy Route entity and assign genereted ID before invoke saveRoute

route.copy(id = Some(BSONObjectID.generate().stringify))

This approach allows me to get both, WriteResult and saved entity

Calorific answered 7/9, 2016 at 13:53 Comment(0)
P
7

That's a (fairly common) design choice made by ReactiveMongo.

The recommended solution is to provide an id yourself, using BSONObjectID.generate, instead of letting the db create one for you.

Here's an example from the ReactiveMongo documentation http://reactivemongo.org/releases/0.11/documentation/tutorial/write-documents.html

val id = BSONObjectID.generate
val person = Person(
  id,
  "Stephane",
  "Godbillon",
  29)

val future = collection.insert(person)

future.onComplete {
  case Failure(e) => throw e
  case Success(lastError) => {
    println(s"successfully inserted document with id $id)
  }
}
Partisan answered 6/9, 2016 at 16:28 Comment(5)
in this case you still need to have non-empty result to get ID.Calorific
@Calorific what do you mean?Partisan
In case of Success I get this object DefaultWriteResult(ok=true, n=1, writeErrors=List(), writeConcernError=None, code=None, errmsg=None) There is no ObjectId in itCalorific
well if you create it at application level, you can just return the reference. I'll update the examplePartisan
there you go, check out the examplePartisan
C
1

I managed to get ID or any other field, or even entire object by returning tuple from save method.

def saveRoute(route: Route)(implicit writer: BSONDocumentWriter[Route]) = {
    collection.insert(route).map((_, route))
  }

I copy Route entity and assign genereted ID before invoke saveRoute

route.copy(id = Some(BSONObjectID.generate().stringify))

This approach allows me to get both, WriteResult and saved entity

Calorific answered 7/9, 2016 at 13:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.