如何使用mongoDB Java驱动程序3.4+或3.6+避免异常过早地到达流的末尾? (插入期间) [英] How to avoid an exception Prematurely reached end of stream using mongoDB Java driver 3.4+ or 3.6+? (during insertion)

查看:83
本文介绍了如何使用mongoDB Java驱动程序3.4+或3.6+避免异常过早地到达流的末尾? (插入期间)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用以下代码片段将一些文档插入有上限的收藏集:

I'm trying to insert some documents to capped collection using this snippet of code:

            // 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));
        }

这意味着-重写文档.我要插入具有更多字段而不是旧文档的新文档,因为加盖的集合不允许用其他尺寸更新现有文档. 自从我遇到一个例外:无法更改上限集合中文档的大小.

It means - rewriting documents. I'm inserting new documents with one more field instead of older docs, because capped collection doesn't allow to update existing document with another size. Since I get an exception: Cannot change the size of a document in a capped collection.

旧文档如下:

新的将是:

此代码可以正常工作,但是过一会儿(在插入过程中),我不断收到错误消息:

And this code works fine, but after a while (during insertion) I'm getting constantly an error:

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)

据我正确理解,该错误出现在行中(可能只是格式问题):

As I correctly understand, the error appears on the line (maybe simply formatting problem):

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

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

I researched and tried to solve the error using this code like (I'm using free Tier M0 cluster):

  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

The same error: com.mongodb.MongoSocketReadException: Prematurely reached end of stream

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

Updated: Tried instead of rewriting full document, to change just one field like:

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


试图更改版本,结果为


Tried to change version , the result is here.

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

Does anyone know what I need to correct or how to solve the error Prematurely reached end of stream?

感谢您的帮助.

推荐答案

选项#1

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

Option #1

The error was solved by the format of connection (using the parameters maxIdleTimeMS, ssl and authSource):

maxIdleTimeMS -的最大毫秒数连接 在删除和关闭之前,可以在池中保持空闲状态.

maxIdleTimeMS - the maximum number of milliseconds that a connection can remain idle in the pool before being removed and closed.

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+版本):


Or you can configure the credentials programmatically (using java driver 3.6+ versions):

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

admin - is the database where the users are defined in 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);

在定义主机名时,请提及所有副本集主机名. 这将解决java.net.UnknownHostException.

When defining the host names, mention all the replica set host names. This will resolve the java.net.UnknownHostException.

  • 您不能像mongodb + srv连接那样使用DNS简称.

    You can't use the DNS short name as with the mongodb+srv connection.


  • 选项#2

    此外,可以通过调用mongodb.MongoClient.connect一次而不是每个请求一次来解决错误.尝试重组代码以在一次插入特定文档时而不是每次调用一次连接.在这种情况下,您可以避免使用选项#1中的任何其他参数.


    Option #2

    Moreover, the error can be solved by calling mongodb.MongoClient.connect once, not each request. Try to restructure your code to call connection once instead of each time during insertion of specific document. In this case, you can avoid any additional parameters from option #1.

    就够了:

    mongodb+srv://admin:password@cluster0-ox90k.mongodb.net/test?retryWrites=true&w=majority
    


    特别感谢您对mongoDB支持的帮助.


    Special thanks for help mongoDB support.

    这篇关于如何使用mongoDB Java驱动程序3.4+或3.6+避免异常过早地到达流的末尾? (插入期间)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆