如何避免exception使用mongoDB Java驱动程序3.4+或3.6+过早地到达流的末尾? (插入期间)

我正在尝试使用以下代码片段将一些文档插入到上限集合中:

// get document with specific fields Document found = collection.find().first(); String getTitle = (String) found.get("title"); String getUrl = (String) found.get("url"); String getImg = (String) found.get("img"); String getPrice = (String) found.get("price"); // document which I want to get as new Document doc = collection.find(new Document("title", getTitle) .append("url", getUrl) .append("img", getImg) .append("price", getPrice) .append("sent", true)).first(); // if the document doesn't exist, then insert as new if (doc == null) { collection.insertOne(new Document("title", getTitle) .append("url", getUrl) .append("img", getImg) .append("price", getPrice) .append("sent", true)); } 

这意味着 – 重写文件。 我正在插入包含一个以上字段而不是旧文档的新文档,因为上限集合不允许使用其他大小更新现有文档。 因为我得到一个例外:无法更改上限集合中文档的大小

较旧的doc看起来像:

在此处输入图像描述

新的将是:

在此处输入图像描述

这段代码工作正常,但过了一段时间(插入过程中)我经常遇到错误:

 com.mongodb.MongoSocketReadException: Prematurely reached end of stream at com.mongodb.connection.SocketStream.read(SocketStream.java:88) at com.mongodb.connection.InternalStreamConnection.receiveResponseBuffers(InternalStreamConnection.java:491) at com.mongodb.connection.InternalStreamConnection.receiveMessage(InternalStreamConnection.java:221) at com.mongodb.connection.CommandHelper.receiveReply(CommandHelper.java:134) at com.mongodb.connection.CommandHelper.receiveCommandResult(CommandHelper.java:121) at com.mongodb.connection.CommandHelper.executeCommand(CommandHelper.java:32) at com.mongodb.connection.InternalStreamConnectionInitializer.initializeConnectionDescription(InternalStreamConnectionInitializer.java:83) at com.mongodb.connection.InternalStreamConnectionInitializer.initialize(InternalStreamConnectionInitializer.java:43) at com.mongodb.connection.InternalStreamConnection.open(InternalStreamConnection.java:115) at com.mongodb.connection.UsageTrackingInternalConnection.open(UsageTrackingInternalConnection.java:46) at com.mongodb.connection.DefaultConnectionPool$PooledConnection.open(DefaultConnectionPool.java:381) at com.mongodb.connection.DefaultConnectionPool.get(DefaultConnectionPool.java:96) at com.mongodb.connection.DefaultConnectionPool.get(DefaultConnectionPool.java:82) at com.mongodb.connection.DefaultServer.getConnection(DefaultServer.java:72) at com.mongodb.binding.ClusterBinding$ClusterBindingConnectionSource.getConnection(ClusterBinding.java:86) at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:237) at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:212) at com.mongodb.operation.FindOperation.execute(FindOperation.java:482) at com.mongodb.operation.FindOperation.execute(FindOperation.java:79) at com.mongodb.Mongo.execute(Mongo.java:772) at com.mongodb.Mongo$2.execute(Mongo.java:759) at com.mongodb.FindIterableImpl$FindOperationIterable.first(FindIterableImpl.java:207) at com.mongodb.FindIterableImpl.first(FindIterableImpl.java:148) at project.Bot.onUpdateReceived(Bot.java:347) 

正如我所理解的那样,错误出现在行上(可能只是格式化问题):

  Document found = collection.find().first(); 

我研究并试图使用这个代码来解决错误(我正在使用免费的Tier M0集群):

  MongoCredential credential = MongoCredential.createCredential("admin1", "admin", "mypassword".toCharArray()); MongoClientSettings settings = MongoClientSettings.builder() .credential(credential) .retryWrites(true) .applyToConnectionPoolSettings(builder -> builder.maxConnectionIdleTime(60000, TimeUnit.MILLISECONDS)) .applyToSocketSettings(builder -> builder.keepAlive(true)) .applyToSslSettings(builder -> builder.enabled(true)) .applyToClusterSettings(builder -> { builder.hosts(Arrays.asList( new ServerAddress("cluster0-shard-00-00-ox90k.mongodb.net", 27017), new ServerAddress("cluster0-shard-00-01-ox90k.mongodb.net", 27017), new ServerAddress("cluster0-shard-00-02-ox90k.mongodb.net", 27017) )); builder.requiredReplicaSetName("Cluster0-shard-0"); }) .build(); MongoClient mongoClient = MongoClients.create(settings); 

同样的错误: com.mongodb.MongoSocketReadException: Prematurely reached end of stream

更新:尝试而不是重写完整文档,只更改一个字段,如:

 Document found = database.getCollection("capped_collection").find(new Document("title", title) .append("url", url) .append("img", img) .append("price", price)).first(); if (found == null) { collection.insertOne(new Document("title", title) .append("url", url) .append("img", img) .append("price", price) .append("sent", false)); Document doc = collection.find(eq("sent", false)).first(); if(doc != null){ collection.updateOne(eq("sent", false), new Document("$set", new Document("sent", true))); } 

但仍然有:

 com.mongodb.MongoSocketReadException: Prematurely reached end of stream 

试图改变版本 ,结果就在这里 。

有谁知道我需要纠正什么或如何解决错误Prematurely reached end of stream

我感谢任何帮助。

错误是通过连接格式解决的(使用参数maxIdleTimeMSsslauthSource ):

maxIdleTimeMS – 连接在删除和关闭之前可以在池中保持空闲的最大毫秒数。

 MongoClient mongoClient = MongoClients.create("mongodb://user:mypassword@cluster0-shard-00-00-ox90k.mongodb.net:27017,cluster0-shard-00-01-ox90k.mongodb.net:27017,cluster0-shard-00-02-ox90k.mongodb.net:27017/test?ssl=true&replicaSet=Cluster0-shard-0&authSource=admin&retryWrites=true&maxIdleTimeMS=5000"); 

或者您可以以编程方式配置凭据(使用java驱动程序3.6+版本):

admin – 是在Atlas中定义用户的数据库;

user – 是用户名;

mypassword – 是密码;

 MongoCredential credential = MongoCredential.createCredential("user", "admin", "mypassword".toCharArray()); MongoClientSettings settings = MongoClientSettings.builder() .credential(credential) .retryWrites(true) .applyToConnectionPoolSettings(builder -> builder.maxConnectionIdleTime(5000, TimeUnit.MILLISECONDS)) .applyToSslSettings(builder -> builder.enabled(true)) .applyToClusterSettings(builder -> { builder.hosts(Arrays.asList( new ServerAddress("cluster0-shard-00-00-ox90k.mongodb.net", 27017), new ServerAddress("cluster0-shard-00-01-ox90k.mongodb.net", 27017), new ServerAddress("cluster0-shard-00-02-ox90k.mongodb.net", 27017) )); builder.requiredReplicaSetName("Cluster0-shard-0"); }) .build(); MongoClient mongoClient = MongoClients.create(settings); 
  1. 定义主机名时,请提及所有副本集主机名。 这将解决java.net.UnknownHostException。

  2. 您不能像使用mongodb + srv连接那样使用DNS短名称。

还要感谢mongoDB支持的帮助。