美文网首页大数据,机器学习,人工智能大数据Java学习笔记
MongoDB:count结果不准确的原因与解决方法

MongoDB:count结果不准确的原因与解决方法

作者: 峰巢 | 来源:发表于2018-03-08 17:34 被阅读2510次

    本人博客同步发表,排版更佳
    教训:MongoDB在分片后的集合上进行db.collection.count()操作时,出现结果不准确的现象,需要采用聚合的方法获取集合的count结果
    在使用MongoDB-Java客户端做简单的插入操作(10W条)以后,使用Studio 3T查看插入结果时,发现显示的count结果与插入的数据不一致,偶然会多出几条或十几条,插入操作很简单,其中table3被分片

    //创建客户端连接
    MongoClient mongoClient = new MongoClient( "xxx.xxx.xxx.xxx" , 20000 );
    MongoDatabase database = mongoClient.getDatabase("testdb");
    MongoCollection<Document> collection = database.getCollection("table3");
    
    //插入文档
    long start = System.currentTimeMillis();
    Random r = new Random();
    for (int i=0;i<100000;i++){
        Document doc = new Document("id", i)
                .append("type", "database"+i)
                .append("test","testval"+i)
                .append("name", "name"+i);
    
        System.out.println("insertOne = " + i);
        collection.insertOne(doc);
    }
    System.out.println("use time = " + (System.currentTimeMillis()- start));
    System.out.println("count = " + collection.count());
    

    发现问题后,通过在shell里面查询count,命令如下

    db.table3.count()
    

    使用该命令依然会出现统计信息不准确的现象,通过谷歌发现,官方文档——(https://docs.mongodb.com/manual/reference/method/db.collection.count/)中有解释这种现象:

    db.collection.aggregate(
       [
          { $group: { _id: null, count: { $sum: 1 } } }
       ]
    )
    

    官方文档解释了这种现象的原因以及解决方法:
    不准确的原因

    • 操作的是分片的集合(前提)
    • shard分片正在做块迁移,导致有重复数据出现
    • 存在孤立文档(因为不正常关机、块迁移失败等原因导致)

    解决方法
    使用聚合aggregate的方式查询count数量,shell命令如下:

    db.collection.aggregate(
       [
          { $group: { _id: null, count: { $sum: 1 } } }
       ]
    )
    

    java代码
    所以在Java中也可以采用聚合的方式获取count结果,使用聚合aggregate的方式可以准确的获取sharding后的集合的count结果。

    DBObject groupFields = new BasicDBObject("_id", null);
    groupFields.put("count", new BasicDBObject("$sum", 1));
    BasicDBObject group = new BasicDBObject("$group", groupFields);
    
    List<BasicDBObject> aggreList = new ArrayList<BasicDBObject>();
    aggreList.add(group);
    AggregateIterable<Document> output = collection.aggregate(aggreList);
    
    for (Document dbObject : output)
    {
          System.out.println("Aggregates count = "+ dbObject);
    }
    

    完整代码

            //创建客户端连接
            MongoClient mongoClient = new MongoClient( "xxx.xxx.xxx.xxx" , 20000 );
            MongoDatabase database = mongoClient.getDatabase("testdb");
            MongoCollection<Document> collection = database.getCollection("table3");
    
            //插入文档
            long start = System.currentTimeMillis();
            Random r = new Random();
            for (int i=0;i<100000;i++){
                Document doc = new Document("id", i)
                        .append("type", "database"+i)
                        .append("test","testval"+i)
                        .append("name", "name"+i);
    
                System.out.println("insertOne = " + i);
                collection.insertOne(doc);
            }
    
            System.out.println("use time = " + (System.currentTimeMillis()- start));
    
            System.out.println("count = " + collection.count());
    
            DBObject groupFields = new BasicDBObject("_id", null);
            groupFields.put("count", new BasicDBObject("$sum", 1));
            BasicDBObject group = new BasicDBObject("$group", groupFields);
    
            List<BasicDBObject> aggreList = new ArrayList<BasicDBObject>();
            aggreList.add(group);
            AggregateIterable<Document> output = collection.aggregate(aggreList);
    
            for (Document dbObject : output)
            {
                System.out.println("Aggregates count = "+ dbObject);
            }
    

    相关文章

      网友评论

        本文标题:MongoDB:count结果不准确的原因与解决方法

        本文链接:https://www.haomeiwen.com/subject/rfvyfftx.html