我们正在使用 Spring-Data-Mongo 从 Java 应用程序访问我们的 MongoDB。一般来说,一切正常,但我遇到了一种奇怪的行为。
在 Java 代码中初始化我们的存储库时,我们使用 ensureIndex 在集合上创建索引。在单元测试中,我们从集合中读取所有索引作为 IndexInfo 对象,并检查这些 IndexInfo 对象是否包含我们要在成员 indexFields 中索引的字段。当我们设置好所有东西时,这也很好用。
现在碰巧我们必须在生产环境中重新创建一个索引,所以我们删除它并使用 Mongo shell 再次创建它。系统似乎运行良好,没有出现任何问题。出于一致性原因,我们随后以相同的方式对我们的测试甚至本地环境进行了相同的更改。然后我们注意到我们的索引检查单元测试失败了,因为 indexField 成员现在是空的。
我尝试了我能想象到的一切,但是一旦我使用 Mongo shell 创建索引,即使我创建具有相同配置的索引,Spring 也不再提供任何索引字段。
谁能告诉我为什么会发生这种情况以及这是否表明存在问题?有没有办法解决这个问题而不必放弃收藏?我正在考虑在我们的下一个生产版本之后删除索引,然后触发插入。在我的本地机器上,这以我期望的方式创建了索引并且测试成功了。
- - 附加信息 - - -
嗨特丽莎,
很抱歉没有早点采取行动,但我有时间为此构建一个小型单元测试。
如果您在空数据库上运行以下测试,它可以正常工作:
@Test
public void testIndexing() throws Exception {
this.mongoTemplate.indexOps("testcollection").ensureIndex(
new Index().on("indexfield", Order.ASCENDING).unique().sparse());
List<IndexInfo> indexInfos = mongoTemplate.indexOps("testcollection").getIndexInfo();
assertEquals("We want two indexes, id and indexfield", 2, indexInfos.size());
for (IndexInfo info : indexInfos) {
assertEquals("All indexes are only meant to have one field", 1, info.getIndexFields().size());
if (info.getName().startsWith("indexfield")) {
assertTrue("Unexpected index field", info.isIndexForFields(Arrays.asList(new String[]{ "indexfield" })));
assertTrue("Index indexfield must be unique", info.isUnique());
assertTrue("Index indexfield must be sparse", info.isSparse());
assertFalse("Index indexfield must not be droping duplicates", info.isDropDuplicates());
} else if (!"_id_".equals(info.getName())) {
fail("Unexpected index: '" + info.getName() + "'");
}
}
}
然后打开 mongo shell 并调用:
db.testcollection.dropIndexes();
db.testcollection.ensureIndex({"indexfield":1}, {"unique":true, "sparse":true})
第二次调用应该创建与 java 代码完全相同的索引。现在,如果您再次运行测试,则 ensureIndex-Method 什么也不做,因为索引已经存在(我猜应该如此),但是在索引字段的断言上测试失败。第一个断言工作正常,因为索引信息在那里。
无论索引是通过 shell 还是通过 java 代码创建的,检查 mongo shell 中的索引都会产生相同的输出,但是当通过 shell 创建索引时,spring 由于某种原因没有获取索引字段。
如果你能给我一个提示,那就太好了。