我无法从我的Scala Mongo查询中获取任何数据

时间:2018-03-27 09:50:44

标签: mongodb scala

我正在尝试从mongo-db数据库中检索一些数据。我已经设置了一个用户帐户,我可以使用命令行工具检索一些数据:

C:\Program Files\MongoDB\Server\3.6\bin\mongo.exe" database.foocorp.com:27017/mydatabase -u salimfadhley -p secretpassowrd
MongoDB shell version v3.6.3
connecting to: mongodb://database.foocorp.com:27017/mydatabase
MongoDB server version: 3.4.4
WARNING: shell and server versions do not match
> db.mycollection.find()
... got loads of data back ...

我能够从Python查询相同的数据集,如下所示:

from pymongo import MongoClient

def main():
    client = MongoClient(
        'database.foocorp.com',
        username='salimfadhley',
        password='secretpassword',
        authsource='dashboard',
        authMechanism='SCRAM-SHA-1'
    )
    db = client.dashboard
    collection = db["mycollection"]
    print(collection.find_one())

if __name__ == "__main__":
    main()

第一次按预期工作完美。

但是现在我想从Scala做同样的事情:

import org.mongodb.scala.{Document, MongoClient, MongoCollection}


object ConnectionDemo extends App {

  val dbHost = "database.foocorp.com"
  val dbPort = 27017
  val dbUserName = "salimfadhley"
  val dbPassword = "secretpassword"
  val dbName = "mydatabase"
  val collectionName = "mycollection"
  val mongoClient = MongoClient(s"mongodb://$dbUserName:$dbPassword@$dbHost:$dbPort/?authsource=$dbName")

  val mongoDatabase = mongoClient.getDatabase(dbName)        
  val result = mongoDatabase.getCollection(collectionName).find()

  result.subscribe(
    (d:Document) => println(d.toJson()),
    (e:Throwable) => println(s"An error occurred, ${e.getMessage}"),
    () => println("Done")

  )

我的期望是这段代码应该为集合中的每件事打印出一个项目。当我使用Robo3T和mongo shell的完全相同的凭证查询集合时,我得到了大量的结果,所以我原本希望在这里看到相同的东西。

实际上这段代码似乎什么都不做:它从不打印任何结果,错误甚至“完成”。

此外,如果我故意提供错误的密码或主机名,它仍然绝对没有。如果连接参数完全错误,我希望看到某种错误消息。

我在这里做错了什么?

2 个答案:

答案 0 :(得分:2)

正如您所指出的,问题是您不等待数据库的响应。我在你的回答中看到你使用Await - 虽然这是一个有效的事情,但如果你希望你的代码是异步的,你应该真的避免使用Await。当您的应用正在等待回复时,它无法做任何其他事情。

常见的解决方法是使用Scala Futures。未来的好处是,在其核心,你假设在某些时候会有响应,并且可以在Future等待完成时继续计算其他东西。如果要使用Future的值,可以在其中进行映射。这假定一旦未来完成,您将对结果做一些事情。使用Future的一般示例:

import scala.concurrent.Future

// assuming you have a method called callDatabase in another class called connector
val thingToWaitFor: Future[String] = ???
thingToWaitFor.map {
  thing => // do something with this thing (thing is now of type String)
}

如果您需要等待多个期货,则需要在所有外部期货上使用Scala的flatMap功能,并且只在最内部的期货上进行映射:

import scala.concurrent.Future

val thingToWaitFor1: Future[String] = ???
val thingToWaitFor2: Future[String] = ???
val thingToWaitFor3: Future[String] = ???

thingToWaitFor1.flatMap {
  thing1 =>
    thingToWaitFor2.flatMap {
      thing2 =>
        thingToWaitFor3.map {
          thing3 => // etc
        }
    }
}

当然,您可以在定义后的任何时候对这些映射值(thing1thing2thing3)执行某些操作,而不仅仅是在最高位置或最低级别。

使用Futures比等待结果更受欢迎,特别是对于异步应用程序。如果您不是异步,那么我认为Await很好。只是觉得我给了另一种选择!

答案 1 :(得分:0)

愚蠢的我,答案是here。我所要做的就是等待结果传递,最简单的方法是使用Scala的“Await”功能。