Spring Data MongoDB Transactions

MongoDB Configuration

@Configuration
@EnableMongoRepositories(basePackages = "com.baeldung.repository")
public class MongoConfig extends AbstractMongoClientConfiguration{

    @Bean
    MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
        return new MongoTransactionManager(dbFactory);
    }

    @Override
    protected String getDatabaseName() {
        return "test";
    }

    @Override
    public MongoClient mongoClient() {
        final ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017/test");
        final MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
            .applyConnectionString(connectionString)
            .build();
        return MongoClients.create(mongoClientSettings);
    }
}

Synchronous Transactions

@Test
@Transactional
public void whenPerformMongoTransaction_thenSuccess() {
    userRepository.save(new User("John", 30));
    userRepository.save(new User("Ringo", 35));
    Query query = new Query().addCriteria(Criteria.where("name").is("John"));
    List<User> users = mongoTemplate.find(query, User.class);

    assertThat(users.size(), is(1));
}

Note that we can’t use listCollections command inside a multi-document transaction – for example:

References
https://www.baeldung.com/spring-data-mongodb-transactions

Create Indexes in Spring Data MongoDB

Using @Indexed
This annotation marks the field as indexed in MongoDB:

@QueryEntity
@Document
public class User {
    @Indexed
    private String name;
    
    ... 
}

but as of Spring Data MongoDB 3.0, automatic index creation is turned off by default.

We can, however, change that behavior by explicitly overriding autoIndexCreation() method in our MongoConfig:

public class MongoConfig extends AbstractMongoClientConfiguration {

    // rest of the config goes here

    @Override
    protected boolean autoIndexCreation() {
        return true;
    }
}

We can create other types of index using these attributes :

@Indexed
@TextIndexed
@HashIndexed
@GeoSpatialIndexed
@WildcardIndexed
@GeoIndexed

Create an Index Programmatically

mongoOps.indexOps(User.class).
  ensureIndex(new Index().on("name", Direction.ASC));

Compound Indexes

MongoDB supports compound indexes, where a single index structure holds references to multiple fields.

@QueryEntity
@Document
@CompoundIndexes({
    @CompoundIndex(name = "email_age", def = "{'email.id' : 1, 'age': 1}")
})
public class User {
    //
}

References
https://www.baeldung.com/spring-data-mongodb-index-annotations-converter
https://careydevelopment.us/blog/spring-boot-and-mongotemplate-how-to-handle-a-full-text-search
https://spring.io/blog/2014/07/17/text-search-your-documents-with-spring-data-mongodb
https://mongodb.github.io/mongo-java-driver/3.4/driver/tutorials/indexes/
https://www.mongodb.com/docs/manual/indexes/

Initialize MongoDB Repositories using ApplicationContextAware in Spring Boot

@Component
public class ApplicationContextProvider implements ApplicationContextAware {
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        DB.mongoTemplate=applicationContext.getBean(MongoTemplate.class);
        DB.monitoringItemRepository = applicationContext.getBean(MonitoringItemRepository.class);
    }
}
public class DB {
    public static MongoTemplate mongoTemplate=null;
    public static MonitoringItemRepository monitoringItemRepository = null;
}

References
https://zetcode.com/springboot/applicationcontext/

Configure Spring Boot to Connect to MongoDB with Credential

@Configuration
public class MongoConfig extends AbstractMongoClientConfiguration {
    /*
     * Use the standard Mongo driver API to create a com.mongodb.client.MongoClient instance.
     */
    public MongoClient mongoClient() {
        //String connectionString = "mongodb://username:password@localhost:27017/?authSource=admin&authMechanism=SCRAM-SHA-1";
        MongoCredential credential = MongoCredential.createScramSha256Credential("username", "admin", "password".toCharArray());
        MongoClient mongoClient = MongoClients.create(
                MongoClientSettings.builder()
                        .applyToClusterSettings(builder ->
                                builder.hosts(Arrays.asList(new ServerAddress("localhost", 27017))))
                        .credential(credential)
                        .build());
        return mongoClient;
    }

    @Override
    protected String getDatabaseName() {
        return "databaseName";
    }

    @Override
    public Collection getMappingBasePackages() {
        return Collections.singleton("net.pupli");
    }
}

References
https://www.baeldung.com/spring-data-mongodb-tutorial
https://www.mongodb.com/docs/drivers/java/sync/current/fundamentals/auth/
https://www.mongodb.com/docs/manual/reference/connection-string/

Create Indexes in MongoDB via .NET

static async Task CreateIndexAsync()
{
    var client = new MongoClient();
    var database = client.GetDatabase("HamsterSchool");
    var collection = database.GetCollection<Hamster>("Hamsters");
    var indexKeysDefinition = Builders<Hamster>.IndexKeys.Ascending(hamster => hamster.Name);
    await collection.Indexes.CreateOneAsync(new CreateIndexModel<Hamster>(indexKeysDefinition));
}

References
https://stackoverflow.com/questions/17807577/how-to-create-indexes-in-mongodb-via-net

MongoDB.Driver.MongoAuthenticationException: Unable to authenticate using sasl protocol mechanism SCRAM-SHA-1

The issue is you are authenticating the mongoadmin user for clientdb. But mongoadmin user is authenticated to admin db. Get the mongoadmin user authenticated and then you can access clientdb.

IMongoClient _client;
        public readonly IMongoDatabase _database;

        public MongoContext_URIBased()
        {
            var mongoUrl = new MongoUrl("mongodb://mongoadmin:[email protected]:2020/admin");
            _client = new MongoClient(mongoUrl);
            _database = _client.GetDatabase("clientdb");
        }

References
https://stackoverflow.com/questions/53756773/unable-to-connect-to-mongodb-using-authentication-using-mongocsharpdriver-2-7

Use MongoDB createIndex in Java

private MongoCollection<Document> createCollection(String collectionName) {
    String indexFieldName1 = "itemId";
    String indexFieldName2 = "time";
    MongoCollection<Document> mongoCollection = this.database.getCollection(collectionName);

    if (mongoCollection == null) {
        this.database.createCollection(collectionName);
        mongoCollection = this.database.getCollection(collectionName);
    }

    IndexOptions indexOptions1 = new IndexOptions().unique(false)
            .background(false).name(indexFieldName1);
    Bson keys1 = new Document(indexFieldName1, Integer.valueOf(1));
    mongoCollection.createIndex(keys1, indexOptions1);

    IndexOptions indexOptions2 = new IndexOptions().unique(false)
            .background(false).name(indexFieldName2);
    Bson keys2 = new Document(indexFieldName2, Integer.valueOf(1));
    mongoCollection.createIndex(keys2, indexOptions2);

    return mongoCollection;
}

References
https://www.programcreek.com/java-api-examples/?class=com.mongodb.client.MongoCollection&method=createIndex