0

我的程序将执行以下操作(使用 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 shelldb.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

请参阅罗斯的详细答案以获取完整的故事。

4

1 回答 1

2

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

底层的 java 代码缓存不知道你在 shell 中做什么,它期望成为 true 的唯一来源(其他驱动程序也遵循这种模式)。之所以有缓存是为了提高性能,这样确保索引可以重复调用,对性能影响很小。

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

  1. 仅使用 Casbah 驱动程序来创建和管理索引 - ensureIndex 依赖什么
  2. 仅使用 shell 创建和管理索引 - shell 不缓存
  3. 不要相信 Casbah 代码中的缓存

您可以完全调用createIndex并绕过缓存。对此有一张 jira 票:JAVA-667,它会寻找下一个主要版本(3.0),正在删除缓存。

于 2013-11-07T14:46:52.880 回答