MongoTemplate bulk upsert fails to update the collection

I’ve got a MongoDB collection with the following document structure:

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@Document
public class CustomerRouteManagementReportDocument implements TransactionDocument {
    @Id
    private String id;
    @Indexed(unique = true)
    private String customerId;
    // ... other properties
    private List<RouteHistoryEvent> routeHistoryEvents;
    // ... other properties
}

Essentially, the following method should perform a bulk upsert: if a matching entry is found, it should append the first item from the routeHistoryEvents item into the existing document’ routeHistoryEvents array. Otherwise, a whole new CustomerRouteManagementReportDocument should be inserted into the collection.

@Service
@Slf4j
public class CustomerRouteManagementReportRepositoryAdapter extends AbstractRepositoryAdapter<CustomerRouteManagementReport, CustomerRouteManagementReportDocument, CustomerRouteManagementReportDataRepository> implements CustomerRouteManagementReportRepository {

    private final MongoTemplate mongoTemplate;
    @Autowired
    public CustomerRouteManagementReportRepositoryAdapter(ModelMapper mapper, CustomerRouteManagementReportDataRepository repository, MongoTemplate mongoTemplate) {
        super(mapper, repository, CustomerRouteManagementReport.class, CustomerRouteManagementReportDocument.class);
        this.mongoTemplate = mongoTemplate;
    }
    //... other methods

    @Override
    public Integer upsertTall(List<CustomerRouteManagementReportDocument> customerRouteManagementReports) {
        BulkOperations bulkOps = mongoTemplate.bulkOps(BulkOperations.BulkMode.ORDERED, CustomerRouteManagementReportDocument.class);

        try {
            List<Pair<Query, Update>> updates = new ArrayList<>();

            customerRouteManagementReports.stream().forEach(customerRouteManagementReport -> {
                Query query = Query.query(Criteria.where("customerId").is(customerRouteManagementReport.getCustomerId()));
                Update update = new Update();

                update.addToSet("routeHistoryEvents").value(customerRouteManagementReport.getRouteHistoryEvents().get(0));
                updates.add(Pair.of(query, update));

            });

            bulkOps.upsert(updates);
            BulkWriteResult result = bulkOps.execute();
            log.info("== BULK RESULT: {}, INSERTED: {}", result, result.getInsertedCount());
            return result.getInsertedCount();
        }

        catch (Exception e) {
            log.error("ERROR {}: IN UPSERTION  {}", e.getClass().toGenericString(), e.getMessage());
            return 0;
        }
    }
}

The problem is that no updates nor insertions are being made and no exception is raised either. I’ve tried with both an empty collection and a collection loaded with documents that will meet the query condition and should be updated, but my log simply reads:
== BULK RESULT: AcknowledgedBulkWriteResult{insertedCount=0, matchedCount=4, removedCount=0, modifiedCount=4, upserts=[]}, INSERTED: 0

However, in debugging, the method is called and it shows the appropriate number of Pairs for the number of objects that the usecase receives to process:

No MongoTemplate logs are issued (not even for the find operation that, I presume, it must perform in order to update my collection) which leads me to think that maybe my class doesn’t have a proper MongoTemplate configured. However, there are no connection errors thrown either. This is our config class for MongoDB:

@Configuration
@ConditionalOnProperty(name = "spring.data.mongodb.uri-report")
@EnableReactiveMongoRepositories(basePackages = "package name",
        reactiveMongoTemplateRef = ReportMongoConfig.REPORT_REACTIVE_MONGO_TEMPLATE)
public class ReportMongoConfig {

    protected static final String REPORT_REACTIVE_MONGO_TEMPLATE = "reportReactiveMongoTemplate";

    @Value("${spring.data.mongodb.uri-report}")
    private String connectionStringReport;

    @Bean
    public ConnectionString getConnectionDataBaseReport() {
        return new ConnectionString(connectionStringReport);
    }

    @Bean
    public ReactiveMongoTemplate reportReactiveMongoTemplate(MappingMongoConverter mappingMongoConverter) {
        return new ReactiveMongoTemplate(reactiveReportMongoDatabaseFactory(getConnectionDataBaseReport()), mappingMongoConverter);
    }

    @Bean
    public MongoTemplate mongoTemplate(MappingMongoConverter mappingMongoConverter) {
        return new MongoTemplate(reportMongoDBFactory(getConnectionDataBaseReport()), mappingMongoConverter);
    }

    @Bean
    public ReactiveMongoDatabaseFactory reactiveReportMongoDatabaseFactory(ConnectionString getConnectionDataBaseExperience) {
        return new SimpleReactiveMongoDatabaseFactory(getConnectionDataBaseExperience);
    }

    @Bean
    public MongoDbFactory reportMongoDBFactory(ConnectionString connectionString) {
        return new SimpleMongoClientDbFactory(connectionString);
    }

}

I’m wondering if there’s an injection issue when providing the appropriate MongoTemplate bean to the repository class or if there’s an issue with the queries built inside the upsertAll method.

Hi @Daniel_Santiago_Rocha_Morales and welcome to the community forum. :star:

To help you triage further, could you help me understand if you are seeing the similar issue while working on the shell?
If yes, could you confirm if you are using the correct customer_id in the upsert query.

If the issue only persists on the application end, could you help us with some stack trace and some logging information by adding DEBUG level logs in the above condition?

Best Regards
Aasawari

1 Like