2013-11-05 38 views
0

我的程序将执行以下操作(使用卡斯巴):在卡斯巴问题创建索引

load2000DocsIntoMongo() 
def myIndexExists= collection.getIndexInfo().exists(x => x.getAs[String] 
     ("name").getOrElse("") == MY_INDEX_NAME) 
if (myIndexExists) println("log exists") 
else { 
    val start = System.nanoTime() 
    collection.ensureIndex(MY_INDEX) 
    println((System.nanoTime - start)/1000000000 + "seconds to index") 
} 

当从头开始mongod,然后运行我的测试,该指数的作品。运行测试后,我检查db.collection.getIndexes()以查看它是否已创建。

但是,运行我的测试一次后,然后运行db.collection.drop(),我重新运行测试。测试会正确插入文档,但不正确地报告该索引已创建。我这样说,因为即使索引X秒被打印出来,Mongo shell的db.collection.getIndexes()也显示它没有被创建。

为什么不是collection.ensureIndex(MY_INDEX)总是创建索引,如果它不存在?

编辑

当通过collection.ensureIndex(MY_INDEX)添加索引,卡斯巴称为Java库的方法来创建一个索引。在此方法中,使用此索引更新了私人地图变量_createdIndexes

当我修改了蒙戈的指标Java库之外,它不知道更新_createdIndexes变量。因此,当试图创建相同索引时,由于库的缓存(即变量)已将该索引放入其映射中,因此_createdIndexes已具有该值,因此它简称为return;

要解决此问题,请拨打collection.dropIndexes(),这将清除变量的_createdIndexes变量。

Casbah source - https://github.com/mongodb/casbah/blob/master/casbah-core/src/main/scala/MongoCollection.scala

Java source - https://github.com/mongodb/mongo-java-driver/blob/master/src/main/com/mongodb/DBCollection.java

请参阅Ross的完整故事详细的解答。

+0

您正在经历一些奇怪的事情而无法使用该代码进行调试。您在代码中使用了“MY_INDEX_NAME”,但在您的问题中使用了“MY_INDEX”。向我们展示第二次调用'ensureIndex'的结果。 Mongo shell比Casbah更多地使用,试图在那里重现问题(插入单个文档就足够了)。 – ixe013

+0

对不起,MY_ INDEX字段是相同的 - 错字。 –

+0

这可能是一个Mongo错误。我通过电子邮件发送了维护Casbah的软件工程师。有一次我听到这个人的消息。 –

回答

2

它不是每个sae的错误,但我同意这突出显示了一个问题,如果您同时使用Casvah驱动程序和shell或其他驱动程序。

底层java代码缓存不知道你在shell中做了什么,它期望是唯一的真正的源(其他驱动程序也遵循这种模式)。存在缓存的原因是为了提高性能,因此可以重复调用ensureIndex并且对性能影响不大。

所以问题是这种情况下最好的行动方案是什么?

  1. 仅使用卡斯巴驱动程序来创建和管理指标 - 什么ensureIndex依靠
  2. 仅使用shell来创建和管理指标 - 壳犯规缓存
  3. 不要相信在卡斯巴代码缓存

您可以拨打createIndex并完全绕过缓存。这里有一个jira票据:JAVA-667,它寻找下一个主要版本(3.0)缓存被删除。