3

我有一个 groovy 脚本,它使用 Mongo Java 驱动程序 mongo-java-driver-2.8.0.jar 来访问单个集合中的所有记录,更新任何与预期结构不匹配的记录。该脚本像冠军一样工作,但我不知道为什么它处理的记录比集合实际拥有的记录多。或者,更准确地说,dbCursore.hasNext() 迭代的记录多于集合实际拥有的记录。仅当脚本找到要更新的内容时才会发生这种情况。如果脚本在没有更新的情况下执行,则处理的总数是正确的。

hasNext() 是否“重新开始”或记录是否在迭代中移动(如果它们已更新)?

这是代码...

static def doIt( mongo, normalizer, isDryRun ) {
    def ttlProcessed = 0
    def ttlCandidates = 0
    def ttlUpdated = 0
    def lapCount = 0;
    def lapStartTime = System.currentTimeMillis();

    def db = mongo.getDB( "devices" )
    DBCollection dbCollection = db.getCollection( "profiles" )
    DBCursor dbCursor = dbCollection.find();
    while ( dbCursor.hasNext() ) {
        DBObject source = dbCursor.next();
        DBObject normalized = normalizer.normalize( source )
        // Only update if changed...
        if ( ! ( source.equals( normalized ) ) ) {
            ttlCandidates++
            if ( !isDryRun ) {
                BasicDBObject searchQuery = new BasicDBObject( "_id", normalized.get( "_id" ) )
                WriteResult result = dbCollection.update( searchQuery, normalized, false, false, WriteConcern.SAFE );
                ttlUpdated++
            }
        }
        ttlProcessed++;
        if ( ttlProcessed % 10000 == 0 ) {
            printErr "split: ${lapCount}, splitElapsed: ${calcElapsed( lapStartTime) } ms, elapsed: ${calcElapsed( startTime )} ms, processed: ${ttlProcessed}, candidates: ${ttlCandidates}, updated: ${ttlUpdated}"
            lapCount++
            lapStartTime = System.currentTimeMillis()
        }
    }
    printErr "split: ${lapCount}, splitElapsed: ${calcElapsed( lapStartTime) } ms, elapsed: ${calcElapsed( startTime )} ms, processed: ${ttlProcessed}, candidates: ${ttlCandidates}, updated: ${ttlUpdated}"
}

如果运行更新任何记录, ttlProcessed 如何获得高于正在处理的集合计数的值?

4

1 回答 1

5

这可能是因为更新导致文档移动(通常是因为增长)。如果文档确实增长并再次处理,它将被视为一次迭代,但假设您的更新是幂等的(我没有测试过),那么这不会是一个问题。

如果这是一个问题,您可以使用该$snapshot 选项来解决此问题。我还建议阅读以下内容:

http://www.mongodb.org/display/DOCS/How+to+do+Snapshotted+Queries+in+the+Mongo+Database

这些问题本质上是为什么像 mongodump 和 mongoexport 这样的工具会遍历 _id 索引(即$snapshot默认使用)。

如果您想首先防止移动,请查看“填充因子”页面上的此部分:

http://www.mongodb.org/display/DOCS/Padding+Factor#PaddingFactor-ManualPadding

2.2 中还有一些选项可以在运行 compact 命令时设置填充:

http://docs.mongodb.org/manual/release-notes/2.2/#padding-specifiable-on-compact-command

于 2012-08-27T16:20:53.453 回答