在Casbah问题中创建索引

时间:2013-11-05 04:34:08

标签: mongodb

我的程序将执行以下操作(使用Casbah):

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)添加索引时,Casbah调用Java库的方法来创建索引。在此方法中,使用此索引更新了私有地图变量 _createdIndexes

当我修改了Java库的Mongo索引 之外时,它不知道更新 _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详细解答。

1 个答案:

答案 0 :(得分:2)

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

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

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

  1. 仅使用Casbah驱动程序创建和管理索引 - ensureIndex依赖于
  2. 仅使用shell创建和管理索引 - shell不缓存
  3. 不信任Casbah代码中的缓存
  4. 您可以致电createIndex并完全绕过缓存。这上面有一个jira票证:JAVA-667它会查找正在删除缓存的下一个主要版本(3.0)。