@Override
    public void upgrade() {
        boolean indexExists = false;
        for (Document document : collection.listIndexes()) {
            if (MongoDbGrokPatternService.INDEX_NAME.equals(document.getString("name")) && document.getBoolean("unique")) {
                indexExists = true;
                break;
            }
        }

        if (indexExists) {
            LOG.debug("Unique index for Grok patterns already exists, skipping migration.");
            return;
        }

        final Collection<String> grokPatterns = new HashSet<>();
        final Map<ObjectId, String> duplicatePatterns = new HashMap<>();
        for (Document document : collection.find()) {
            final ObjectId id = document.getObjectId("_id");
            final String name = document.getString("name");
            final String pattern = document.getString("pattern");
            if (grokPatterns.contains(name)) {
                LOG.info("Marking duplicate Grok pattern <{}> for removal: {}\t{}", id, name, pattern);
                duplicatePatterns.put(id, name);
            } else {
                LOG.debug("Recording Grok pattern <{}>: {}\t{}", id, name, pattern);
                grokPatterns.add(name);
            }
        }

        for (ObjectId id : duplicatePatterns.keySet()) {
            LOG.info("Deleting duplicate Grok pattern with ID <{}>", id);
            collection.deleteOne(eq("_id", id));
        }

        final IndexOptions indexOptions = new IndexOptions()
                .name(MongoDbGrokPatternService.INDEX_NAME)
                .unique(true);
        collection.createIndex(Indexes.ascending("name"), indexOptions);

        if (!duplicatePatterns.isEmpty()) {
            clusterEventBus.post(GrokPatternsDeletedEvent.create(ImmutableSet.copyOf(duplicatePatterns.values())));
        }

        indexCreated = true;
    }
@Test
    public void insertingDuplicateGrokPatternsIsNotPossibleAfterUpgrade() {
        collection.insertOne(grokPattern("FOO", "[a-z]+"));

        migration.upgrade();

        assertThatThrownBy(() -> collection.insertOne(grokPattern("FOO", "[a-z]+")))
                .isInstanceOf(MongoWriteException.class)
                .hasMessageMatching(".*E11000 duplicate key error collection: graylog.grok_patterns index: idx_name_asc_unique dup key: \\{ (name)?: \"FOO\" \\}.*");
    }