【发布时间】:2019-03-05 18:13:06
【问题描述】:
我正在尝试使用此 sn-p 代码将一些文档插入到 capped 集合中:
// 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));
}
这意味着 - 重写文档。我正在插入具有更多字段而不是旧文档的新文档,因为上限集合不允许使用其他大小更新现有文档。 因为我得到一个例外:无法更改上限集合中文档的大小。
旧文档看起来像:
新的将是:
这段代码工作正常,但过了一段时间(插入期间)我不断收到错误:
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();
我研究并尝试使用此code 解决错误(我正在使用免费的 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?
感谢您的帮助。
【问题讨论】:
-
需要澄清一点:1)如果插入后需要修改文档,是真的需要capped collection,还是需要TTL索引? (见docs.mongodb.com/manual/core/index-ttl)。 2)“过早到达流的末尾”通常是服务器/网络问题,这是一组不同的问题与上限集合中的文档修改。你想问哪个问题? 3) Atlas 应该有一个选项可以显示正确的连接字符串。您是否尝试过在
MongoClient.create()中使用它而不是使用new MongoClient()? -
关于上限集合:如果上限集合中的文档会改变文档的大小,则您不能修改该文档。但是,如果它不改变大小,您可以修改它。例如,如果您插入带有
{_id:.., title:..., uri:..., img:..., price:..., sent:false}的原始文档,如果您随后进行更新,例如db.collection.updateOne({_id:..}, {$set: {sent:true}})不会改变文档大小(只设置false->true),更新成功。 -
@KevinAdistambha,在插入过程中抛出“过早到达流尾”,所以我不能插入所有新文档而不是旧文档。我想我需要使用一些options 来修改我的连接字符串。
-
Re: 连接字符串,如果你在Atlas中点击“连接”按钮,然后点击“连接你的应用程序”,“驱动程序3.6或更高版本”,它会显示你需要的连接字符串。就我而言,它显示
mongodb+srv://kevinadi:<PASSWORD>@cluster0-wsdgm.mongodb.net/test?retryWrites=true。我使用MongoClients.create(...)将该字符串放入测试Java应用程序中,它可以连接到Atlas。 -
是的,你可以。有关完整矩阵,请参阅 Java driver language compatibility list。