3

我有一个上限集合,它是在 java 代码中创建的:

this.collection = db.createCollection("stat", new BasicDBObject("capped", true).append("size", 200000000).append("max", 1000000));

现在在这个集合的统计数据中,我们有:

/* 0 */
{
    "ns" : "myDatabase.stat",
    "count" : 12212,
    "size" : 2146416,
    "avgObjSize" : 175,
    "storageSize" : 200003584,
    "numExtents" : 1,
    "nindexes" : 4,
    "lastExtentSize" : 200003584,
    "paddingFactor" : 1,
    "systemFlags" : 1,
    "userFlags" : 0,
    "totalIndexSize" : 2272928,
    "indexSizes" : {
        "_id_" : 1259104,
        "downloaded_1" : 335216,
        "submitted_1" : 318864,
        "retries_1" : 359744
    },
    "capped" : true,
    "max" : 1000000,
    "ok" : 1
}

如果我尝试使用以下代码在集合中插入文档:

BasicDBObject doc = new BasicDBObject().
        append("downloaded", new Date(0)).
        append("sessionId", sessionId).
        append("group", group);
collection.update(new BasicDBObject("_id", request.getUrl()), new BasicDBObject("$set", doc), true, false);

我发现了这个错误:

com.mongodb.WriteConcernException: { "serverUsed" : "/127.0.0.1:27017" , "lastOp" : { "$ts" : 0 , "$inc" : 0} , "connectionId" : 16420 , "err" : "failing update: objects in a capped ns cannot grow" , "code" : 10003 , "n" : 0 , "ok" : 1.0}
        at com.mongodb.CommandResult.getException(CommandResult.java:77)
        at com.mongodb.CommandResult.throwOnError(CommandResult.java:110)
        at com.mongodb.DBTCPConnector._checkWriteError(DBTCPConnector.java:102)
        at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:142)
        at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:115)
        at com.mongodb.DBApiLayer$MyCollection.update(DBApiLayer.java:327)
        at com.mongodb.DBCollection.update(DBCollection.java:178)
        at com.mongodb.DBCollection.update(DBCollection.java:209)
        at com.srg.hydra.monitoring.HydraStatistics.insert(HydraStatistics.java:63)
        at com.srg.hydra.HydraSite.onSubmit(HydraSite.java:91)
        at ru.decipher.site.AbstractSite.submit(AbstractSite.java:198)
        at com.srg.hydra.Eip.start(Eip.java:48)
        at com.srg.hydra.runner.DefaultHydraRunner.doCrawling(DefaultHydraRunner.java:180)
        at com.srg.hydra.runner.DefaultHydraRunner$1.run(DefaultHydraRunner.java:155)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:744)

我究竟做错了什么?以及如何解决?(排除到 .drop() 这个集合并重新创建)感谢您的回答!

4

1 回答 1

2

您无法更新上限集合中的文档。(如果您阅读了我的整个答案,可以找到解决方法)。我过去遇到过这个问题。请从以下 MongoDB 文档中找到此问题的详细信息(和解决方案):

建议和限制

  • 您只能对文档进行就地更新。如果更新操作导致文档超出其原始大小,则更新操作将失败。

  • 如果您计划更新上限集合中的文档,请创建索引,以便这些更新操作不需要表扫描。

  • 如果您将上限集合中的文档更新为小于其原始大小的大小,然后辅助从主重新同步,辅助将根据当前较小的文档大小复制和分配空间。如果主节点随后接收到将文档增加到其原始大小的更新,则主节点将接受更新,但辅助节点将因更新失败而失败:上限 ns 中的对象无法增长错误消息。

  • 为防止出现此错误,请从副本集的其他最新成员之一的快照创建辅助节点。按照我们关于文件系统快照的教程为您的新辅助节点播种。

  • 使用文件系统快照播种次要文件是保证主要和次要二进制文件兼容的唯一方法。在这种情况下,MMS 备份快照是不够的,因为您需要的不仅仅是辅助的内容来匹配主。

  • 您不能从有上限的集合中删除文档。要从上限集合中删除所有记录,请使用“emptycapped”命令。要完全删除集合,请使用 drop() 方法。

  • 您不能对有上限的集合进行分片。

  • 默认情况下,2.2 之后创建的 Capped 集合具有 _id 字段和 _id 字段上的索引。默认情况下,在 2.2 之前创建的上限集合在 _id 字段上没有索引。如果您在 2.2 之前使用带有复制的上限集合,则应在 _id 字段上显式创建索引。

于 2014-09-12T11:17:52.613 回答