Mongodb 我能';我无法从Scala Mongo查询中获取任何数据

Mongodb 我能';我无法从Scala Mongo查询中获取任何数据,mongodb,scala,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.co

我正在尝试从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提供的完全相同的凭证查询集合时,我得到了大量的结果,所以我希望在这里看到同样的结果

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

此外,如果我故意输入错误的密码或主机名,它仍然完全不起作用。如果连接参数完全错误,我希望看到某种错误消息


我做错了什么

愚蠢的我,答案已经给出了。我所要做的就是等待结果发布,最简单的方法就是使用Scala的“wait”函数。

愚蠢的我,答案已经给出了。我所要做的就是等待结果交付,最简单的方法是使用Scala的“wait”函数。

正如您所指出的,问题是您没有等待数据库的响应。我在您的回答中看到,您使用了wait——虽然这是一种有效的做法,但如果您希望代码是异步的,那么您应该真正避免使用wait。当你的应用程序正在等待响应时,它实际上不能做任何其他事情

解决这个问题的一个常见方法是使用。未来的好处在于,在其核心,你假设在某个时刻会有一个响应,并且可以在未来等待完成时继续计算其他东西。如果你想使用未来的价值,你可以在它里面映射。这假设一旦将来完成了,您将对结果做一些事情。使用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函数,并且只在最内部期货上使用map:

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
        }
    }
}
当然,一旦定义了这些映射值(
thing1
thing2
thing3
),您可以在任何时候对它们进行处理,而不仅仅是在最高或最低级别


使用Futures比只等待结果要好得多,特别是对于异步应用程序。如果您不是异步的,那么我想等待是可以的。我只是想给你另一个选择

正如您所指出的,问题在于您没有等待数据库的响应。我在您的回答中看到,您使用了wait——虽然这是一种有效的做法,但如果您希望代码是异步的,那么您应该真正避免使用wait。当你的应用程序正在等待响应时,它实际上不能做任何其他事情

解决这个问题的一个常见方法是使用。未来的好处在于,在其核心,你假设在某个时刻会有一个响应,并且可以在未来等待完成时继续计算其他东西。如果你想使用未来的价值,你可以在它里面映射。这假设一旦将来完成了,您将对结果做一些事情。使用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函数,并且只在最内部期货上使用map:

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
        }
    }
}
当然,一旦定义了这些映射值(
thing1
thing2
thing3
),您可以在任何时候对它们进行处理,而不仅仅是在最高或最低级别

使用Futures比只等待结果要好得多,特别是对于异步应用程序。如果您不是异步的,那么我想等待是可以的。我只是想给你另一个选择