4

I am trying to print results from a MongoDB query in Scala

val mongoClient: MongoClient = MongoClient()
val database: MongoDatabase = mongoClient.getDatabase("tableScala")
val collection: MongoCollection[Document] = database.getCollection("tableScala")

collection.find().printResults()

The error thrown was : Cannot resolve symbol printResults. Answers to some other questions suggested to use mongo-scala-driver version 1.2, as printResults() is not implemented for version 1.1 and below

SBT file:

name := "scalaMongoDriver"

version := "1.0"

scalaVersion := "2.11.8"

libraryDependencies += "org.mongodb.scala" %% "mongo-scala-driver" % "1.2.0-beta1"

Tried to print manually using :

collection.find().subscribe(
      (user: Document) => println(user.toJson()),                         // onNext
      (error: Throwable) => println(s"Query failed: ${error.getMessage}"), // onError
      () => println("Done")                                               // onComplete
    ) 

resulted in the following info:

INFO: No server chosen by ReadPreferenceServerSelector{readPreference=primary} from cluster description ClusterDescription{type=UNKNOWN, connectionMode=SINGLE, serverDescriptions=[ServerDescription{address=localhost:27017, type=UNKNOWN, state=CONNECTING}]}. Waiting for 30000 ms before timing out

Is there any way to view the retrieved results in console?

starball
  • 20,030
  • 7
  • 43
  • 238
vdep
  • 3,541
  • 4
  • 28
  • 54

4 Answers4

9

You have to include Helpers.scala file to use the printResults() function. It is located in their github repository Helpers.scala.

These helper functions waits for the observable to finish before it prints the values.

Luke Kroon
  • 1,016
  • 12
  • 19
2

The way that worked for me was adding a Thread.sleep in the end of the code, so the program end after the asynchronous call has the chance to print the elements.

This happens because of the reactive nature of Mongo's Observables, meaning that you have to do most of your operations making the use of Futures.

Just the Thread.sleep should work.

starball
  • 20,030
  • 7
  • 43
  • 238
carvalh0ak
  • 21
  • 2
0

MongoDB driver is asynchronous, to make it synchronouse you may apply some of the monads operators

  1. andThen: Allows the chaining of Observables. collect : Collects all the results into a sequence.
  2. flatMap : Create a new Observable by applying a function to each result of the Observable.
  3. foldLeft : Creates a new Observable that contains the single result of the applied accumulator function. foreach : Applies a function applied to each emitted result.
  4. head : Returns the head of the Observable in a Future.
  5. map : Creates a new Observable by applying a function to each emitted result of the Observable.

Full list of observables:

For example:

val doc = Await.result(myCollection
          .find(and(regex("date", s"^${date}T.*"), equal("field", fieldValue)))
          .sort(descending("timestamp"))
          .first().head(), Duration(10, SECONDS))
0

http://mongodb.github.io/mongo-java-driver/4.9/driver-scala/getting-started/quick-start-primer/

It's defined in the Helpers for the quick tour. Of course you can create/copy them in your project.

xing
  • 464
  • 9
  • 17
  • I'm a bit confused. How does this answer the question? I have the feeling that this needs expansion. – starball May 10 '23 at 21:19
  • The methods involved are not "normal" ingredients of the mongo clients library. They are defined in some helpers as part of the tutorials. That is described in the link above. – xing Jun 12 '23 at 08:31