diff --git a/morphium-core/src/main/java/de/caluga/morphium/IndexDescription.java b/morphium-core/src/main/java/de/caluga/morphium/IndexDescription.java index 672739c3f..146cbe7c8 100644 --- a/morphium-core/src/main/java/de/caluga/morphium/IndexDescription.java +++ b/morphium-core/src/main/java/de/caluga/morphium/IndexDescription.java @@ -45,10 +45,23 @@ public static IndexDescription fromMap(Map incoming) { @SuppressWarnings("unchecked") Map keymap = (Map) incoming.get("key"); for (var k : keymap.keySet()) { + // MongoDB's own naming convention is "_" per key, joined by + // "_" between entries -- there is no separator after the LAST entry. Appending + // "_" unconditionally after every entry (as this used to do) produces a + // trailing underscore ("campaignNumber_1_" instead of "campaignNumber_1"), which + // silently breaks index creation on any database where an index on the same + // field already exists under the correct name: MongoDB rejects the mismatched + // name with "Error 85 - Index already exists with a different name", Morphium + // only logs that as a warning, and the index (with any unique constraint) is + // never created. This bug predates 6.3.0 -- it is present unchanged as far back + // as the v6.2.5 tag -- so it is a plain bugfix, not a behaviour change requiring + // a migration path. + if (sb.length() > 0) { + sb.append("_"); + } sb.append(k); sb.append("_"); sb.append(keymap.get(k).toString()); - sb.append("_"); } incoming.put("name", sb.toString()); } diff --git a/morphium-core/src/test/java/de/caluga/test/mongo/suite/base/IndexDescriptionTest.java b/morphium-core/src/test/java/de/caluga/test/mongo/suite/base/IndexDescriptionTest.java index 5d2a449a5..b6e9ffb1f 100644 --- a/morphium-core/src/test/java/de/caluga/test/mongo/suite/base/IndexDescriptionTest.java +++ b/morphium-core/src/test/java/de/caluga/test/mongo/suite/base/IndexDescriptionTest.java @@ -46,4 +46,30 @@ public void asMapFromMapTest() throws Exception { assertEquals(idx.getHidden(), idx2.getHidden()); assertEquals(idx.getSparse(), idx2.getSparse()); } + + // Regression test: fromMap() used to append a trailing "_" separator after every key + // instead of only BETWEEN keys, producing names like "campaignNumber_1_" instead of the + // MongoDB-standard "campaignNumber_1". That mismatch breaks index creation on any database + // where the correctly-named index already exists (MongoDB rejects it with "Error 85 - Index + // already exists with a different name", which Morphium only logs as a warning). Neither + // pre-existing test above catches this: both set an explicit name, which skips the + // auto-naming branch entirely. + @Test + public void fromMap_singleField_generatesNameWithoutTrailingUnderscore() throws Exception { + var idx = IndexDescription.fromMaps(Doc.of("campaignNumber", 1), null); + assertEquals("campaignNumber_1", idx.getName()); + } + + @Test + public void fromMap_multiField_generatesNameJoinedByUnderscoreWithoutTrailingUnderscore() throws Exception { + var idx = IndexDescription.fromMaps(Doc.of("campaignNumber", 1, "fileName", 1), null); + assertEquals("campaignNumber_1_fileName_1", idx.getName()); + } + + @Test + public void fromMap_explicitName_isNotOverwritten() throws Exception { + var idx = IndexDescription.fromMaps(Doc.of("campaignNumber", 1), + Doc.of("name", "myCustomIndexName")); + assertEquals("myCustomIndexName", idx.getName()); + } }