Mongo Java Driver使用getCollection做分页查询遇到的一些坑

背景

最近在做Mongo上的表数据的迁移,原本应该是DBA要干的活,但是想着DBA排期比较长,加上我们开发的权限又非常有限,而且数据量又没有多少,就想着自己开发个小小的程序从旧实例上查,写到新实例上去算了。于是就遇到了今天要分享的这个坑。

有问题代码

这个方法目的是查询表的所有数据,但是返回的结果实际会有问题,返回来的并非全量数据。原因是分好页之后,在去查询每页的数据的时候都重新再查询了下集合,然后再取分页数据,这个过程中有其他的线程也去修改这个集合的数据,集合数据变化了就会导致查询到的分页数据不正确。

   /**
     * 这个方法目的是查询表的所有数据,但是返回的结果实际会有问题,会出现数据不完整
     * 原因是分好页之后,查询每页的数据的时候都重新查询了集合,这个过程中有其他的线程也去修改这个集合的数据,
     * 集合数据变化了就会导致查询到的分页数据不正确。
     * @param dbName
     * @param tableName
     * @return
     */
    public List<Document> queryCollections_Error(String dbName, String tableName) {
        List<Document> result = new ArrayList<>();

        long count = this.count(dbName, tableName);
        int pageSize = 1000;

        for (int idx = 0; idx < count; idx += pageSize) {
            result.addAll(this.queryCollectionsByPage(dbName, tableName, idx, pageSize));
        }

        return result;
    }

改正后的代码

改正后的代码,是只能保证了在程序开始运行的这一刻mongo表的快照的数据同步到新表是准确的,但是同步程序运行过程中如果表数据发生了变更,这部分数据是没有变更到新实例上面去的,这个大家需要注意。我们的业务是对内的业务,而且数据量不大,因此在同步的时候禁写掉这个服务中断时间可以接受。如果是不可接受服务中断,那么应该要考虑下全量+增量的方案。

    public List<Document> queryCollections(String dbName, String tableName) {
        List<Document> result = new ArrayList<>();

        MongoCollection<Document> mongoCollection = this.mongoClient.getDatabase(dbName).getCollection(tableName);
        long count = mongoCollection.countDocuments();
        int pageSize = 1000;

        for (int idx = 0; idx < count; idx += pageSize) {
            FindIterable<Document> iterable = mongoCollection.find().skip(idx).limit(pageSize);

            iterable.forEach(new Block<Document>() {
                @Override
                public void apply(Document document) {
                    result.add(JSON.parseObject(JSON.toJSONString(document), Document.class));
                }
            });
        }

        return result;
    }

完整代码

下载

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吾鳴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值