当前位置: 首页 > 知识库问答 >
问题:

如何使用mongoDB Java驱动程序3.4或3.6避免异常提前到达流的末尾?(插入时)

祁修诚
2023-03-14

我试图插入一些文档,以上限集合使用此代码片段:

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

这意味着——重写文档。我插入的新文档中有一个字段,而不是旧文档,因为capped collection不允许用另一个大小更新现有文档。因为我遇到了一个例外:无法更改封顶集合中文档的大小。

老医生看起来像:

新版本如下:

这段代码运行良好,但过了一段时间(在插入过程中),我不断收到一个错误:

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.MongoSocketReadExc0019:过早到达流的结尾

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

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

尝试更改版本,结果如下。

有人知道我需要纠正什么或者如何解决错误吗?

谢谢你的帮助。

共有1个答案

孔运珧
2023-03-14

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

MaxIdleTimes—连接在被删除和关闭之前在池中保持空闲的最大毫秒数。

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.6versions):

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

>

  • <区块报价>

    定义主机名时,提及所有副本集主机名。

    这将解决java.net.未知主机异常。

    您不能使用DNS短名称作为mongodb srv连接。

    而且,这个错误可以通过调用mongoDB来解决。MongoClient.connect一次,而不是每次请求。尝试将代码重组为调用连接一次,而不是在插入特定文档期间每次调用。在这种情况下,您可以避免选项#1中的任何附加参数。

    就够了:

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

    特别感谢您对mongoDB的支持。

  •  类似资料:
    • 我尝试为转换器插入ExpressionEvaluatingRequestHandlerAdvise,但我不确定如何正确使用它,消息没有到达路由器或ERROR_CHANNEL_NAME

    • 问题内容: 我被分配了一个项目来开发一组用作存储系统接口的类。要求是该类支持具有以下签名的get方法: 基本上,该方法应该返回与if和仅在after之后被修改的对象相关联。如果存储系统不包含,则该方法应返回null。 我的问题是这样的: 如何处理场景的关键存在,但对象已经 不 被修改? 这很重要,因为使用此类的某些应用程序将是Web服务和Web应用程序。这些应用程序将需要知道是返回404(未找到)

    • 我正在使用Firefox 47.0.1和木偶驱动程序geckodriver-v0。8.0-win32。但我遇到了无法访问的浏览器异常,无法打开。 我的代码片段如下所示: 将异常显示为:- 组织。openqa。硒。遥远的UnreachableBrowserException:无法启动新会话。可能的原因是远程服务器地址无效或浏览器启动失败。构建信息:版本:'2.53.0',版本:'35ae25b',时

    • 问题内容: 我正在使用CSS属性, 如果我使用=>它会在之前打印一个额外的空白页 如果我使用=>,它将在以后打印额外的空白页。 如何避免这种情况? 问题答案: 您也许可以添加 因此最后一个元素将不会获得额外的分页符。 请注意,如果您以浏览器的目标为目标,则IE8不支持:last-child选择器。

    • 我不知道确切的原因,但是我的tableview的滚动条永远不会结束。 这是桌面视图的中间,一切看起来都很好 但当我走到尽头 滚动条没有到达终点... 我想我的约束是可以的(我使用的是autolayout),因为除了滚动条,tableview显示得很好。 我的视图控制器是一个,只包含一个。下面是一个屏幕截图,总结如下: 代码未添加任何约束。你知道我怎么调试这个吗? 提前谢谢 编辑:我试图删除和重新创

    • 我有zuul网关服务器,没有eureka服务发现。 我使用下面显示的yml文件连接微服务和zuul。 当我执行URL超时时,会发生异常