Support of Azure Cosmos DB for Spring Data

CAST supports Azure Cosmos DB via its com.castsoftware.nosqljava extension. Details about how this support is provided for Spring Data source code is discussed below.

Supported Client Libraries

LibraryVersionSupported
Azure spring data cosmosUp to: 3.10.0

Supported Operations

OperationsMethod Supported
Insert
org.springframework.data.repository
  • org.springframework.data.repository.CrudRepository.save
  • org.springframework.data.repository.CrudRepository.saveAll
  • org.springframework.data.repository.reactive.ReactiveCrudRepository.save
  • org.springframework.data.repository.reactive.ReactiveCrudRepository.saveAll
com.microsoft.azure.spring.data.cosmosdb.repository
  • com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository.save
  • com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository.saveAll
  • com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository.save
  • com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository.saveAll
  • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.save
  • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.saveAll
  • com.azure.spring.data.cosmos.repository
    • com.azure.spring.data.cosmos.repository.CosmosRepository.save
    • com.azure.spring.data.cosmos.repository.CosmosRepository.saveAll
    • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.save
    • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.saveAll
    com.microsoft.azure.spring.data.cosmosdb.core
    • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.insert
    • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.insert
    • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.insert
    • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.insert
    • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.insert
    • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.insert
    Select
    org.springframework.data.repository
    • org.springframework.data.repository.CrudRepository.existsById
    • org.springframework.data.repository.CrudRepository.findAll
    • org.springframework.data.repository.CrudRepository.findById
    • org.springframework.data.repository.PagingAndSortingRepository.findAll
    • org.springframework.data.repository.reactive.ReactiveCrudRepository.existsById
    • org.springframework.data.repository.reactive.ReactiveCrudRepository.findAll
    • org.springframework.data.repository.reactive.ReactiveCrudRepository.findAllById
    • org.springframework.data.repository.reactive.ReactiveCrudRepository.findById
    • org.springframework.data.repository.reactive.ReactiveSortingRepository.findAll
    com.azure.spring.data.cosmos.repository
    • com.azure.spring.data.cosmos.repository.CosmosRepository.findById
    • com.azure.spring.data.cosmos.repository.CosmosRepository.findAll
    • com.azure.spring.data.cosmos.repository.CosmosRepository.existsById
    • com.azure.spring.data.cosmos.repository.CosmosRepository.count
    • com.azure.spring.data.cosmos.repository.CosmosRepository.findAllById
    • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.findbyId
    • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.findAll
    • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.existsById
    • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.count
    • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.findAllById
    com.microsoft.azure.spring.data.cosmosdb.repository
    • com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository.findById
    • com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository.findAll
    • com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository.existsById
    • com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository.findAllById
    • com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository.count
    • com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository.findAll
    • com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository.existsById
    • com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository.findAllById
    • com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository.count
    • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveSortingRepository.findAll
    • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.findById
    • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.findAll
    • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.count
    • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.findAllById
    • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.existsById
    com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations
    • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.findAll
    • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.find
    • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.findByIds
    • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.exists
    • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.count
    • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.findById
    com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate
  • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.findById
  • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.find
  • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.findAll
  • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.findByIds
  • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.count
  • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.exists
  • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations
    • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.findAll
    • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.find
    • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.findByIds
    • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.exists
    • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.existsById
    • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.count
    • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.findById
      com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.findById
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.find
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.findAll
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.count
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.exists
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.existsById
      com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.count
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.exists
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.find
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.findAll
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.findById
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.count
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.exists
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.find
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.findAll
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.findById
      Delete
      org.springframework.data.repository
      • org.springframework.data.repository.CrudRepository.delete
      • org.springframework.data.repository.CrudRepository.deleteById
      • org.springframework.data.repository.CrudRepository.deleteAllById
      • org.springframework.data.repository.CrudRepository.deleteAll
      • org.springframework.data.repository.reactive.ReactiveCrudRepository.delete
      • org.springframework.data.repository.reactive.ReactiveCrudRepository.deleteAll
      • org.springframework.data.repository.reactive.ReactiveCrudRepository.deleteAllById
      • org.springframework.data.repository.reactive.ReactiveCrudRepository.deleteById
      com.azure.spring.data.cosmos.repository
      • com.azure.spring.data.cosmos.repository.CosmosRepository.deleteById
      • com.azure.spring.data.cosmos.repository.CosmosRepository.delete
      • com.azure.spring.data.cosmos.repository.CosmosRepository.deleteAll
      • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.deletebyId
      • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.deleteAll
      • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.delete
      com.microsoft.azure.spring.data.cosmosdb.core
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.deleteAll
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.delete
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.deleteCollection
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.deleteById
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.deleteAll
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.deleteById
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.delete
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.deleteCollection
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.delete
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.deleteAll
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.deleteById
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.deleteCollection
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.delete
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.deleteAll
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.deleteById
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.deleteCollection
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.delete
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.deleteAll
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.deleteById
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.delete
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.deleteAll
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.deleteById
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.deleteCollection
      com.microsoft.azure.spring.data.cosmosdb.repository
      • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.deleteById
      • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.deleteAll
      • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.delete
      • com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository.deleteById
      • com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository.deletebyId
      • com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository.deleteAll
      • com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository.delete
      Upsert
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.upsert
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.upsert
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.upsert
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.upsert
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.upsert
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.upsert

      Above mentioned methods are supported for both Synchronous and Asynchronous clients.

      Objects

      IconDescription
      Java CosmosDB Database
      Java CosmosDB Collection
      Java Unknown CosmosDB Database
      Java Unknown CosmosDB Collection
      Link typeSource and destination of linkMethods Supported
      parentLinkBetween CosmosDB Database object and CosmosDB Collection-
      useInsertLinkBetween the caller Java Method objects and CosmosDB Collectionsave
      saveAll
      useSelectLinkBetween the caller Java Method objects and CosmosDB CollectionexistsById
      findById
      findAll
      findAllById
      count
      useDeleteLinkBetween the caller Java Method objects and CosmosDB Collectiondelete
      deleteAll
      deleteById
      deleteAllById

      What results can you expect?

      Some example scenarios are shown below:

      CosmosDB Database Connection from Properties File

      application.properties

      application.properties

      azure.cosmosdb.uri=https://cosmoswithspring.documents.azure.com:443/
      azure.cosmosdb.key=2VanbwRYNeJKCUjb5StsnBKaatDcKGRUckHnlSUVSJXifWL3exjwjP2o6rJpt8fY24MRmtnctzcE8hWAlBsRZw==
      azure.cosmosdb.database=cosmoswithspring
      

      Cosmos DB Client Creation

      @Configuration
      @EnableDocumentDbRepositories
      public class AppConfig extends AbstractDocumentDbConfiguration {
       
          @Value("${azure.documentdb.uri}")
          private String uri;
       
          @Value("${azure.documentdb.key}")
          private String key;
       
          @Value("${azure.documentdb.database}")
          private String dbName;
       
          public DocumentClient documentClient() {
              return new DocumentClient(uri, key, ConnectionPolicy.GetDefault(), ConsistencyLevel.Session);
          }
       
          public String getDatabase() {
              return dbName;
          }
      }
      

      Select Operation

      CreateDocument

         @Autowired
          private AlertRepository alertRepository;
      
          @GetMapping("/all")
          public Iterable getAllAlerts() {
              if (StreamSupport.stream(alertRepository.findAll().spliterator(), false).count() > 0) {
                  return alertRepository.findAll();
              } else {
                  throw new ValidationException("No records found.");
              }
          }
      
       @GetMapping("/count")
          public long countAlert() {
              if (StreamSupport.stream(alertRepository.findAll().spliterator(), false).count() > 0) {
                  return alertRepository.count();
              } else {
                  throw new ValidationException("No records found.");
              }
          }
      

      Insert Operation

      QueryDocuments

       @PostMapping("/add")
          public StatusMessage addAlert(@Valid @RequestBody Alert alert) {
              Alert returnedAlert = alertRepository.save(alert);
              if (returnedAlert.getAlertId().isEmpty()) {
                  throw new ValidationException("Error accessing Cosmos database.");
              }
              return new StatusMessage("200", "Alert Added");
          }
      

      Delete Operation

      DeleteDocument

      @GetMapping("/deleteall")
          public StatusMessage deleteAllAlert() {
              alertRepository.deleteAll();
              
              return new StatusMessage("200", "Alert Deleted");
          }
      
       @DeleteMapping("/delete/{id}")
          public StatusMessage deleteAlert(@PathVariable String id) throws NotFoundException {
              //Optional<Alert> returnedAlert = alertRepository.findById(id);
              if (!alertRepository.existsById(id)) {
                  throw new NotFoundException("No alert found with id: " + id);
              }
              alertRepository.deleteById(id);
              return new StatusMessage("200", "alert deleted.");
          }
      

      Query Method Support

      Repo with query method

      @Repository
      public interface AlertRepository extends CosmosRepository<Alert, String> {
      // repo for alert
          List<Alert> findById(String priority);
      }
      

      Controller

      @GetMapping("find/{id}")
          public Alert findAlert(@PathVariable String id) throws NotFoundException {
              return alertRepository.findById(id).orElseThrow(
                      () -> new NotFoundException("No alert found with id: " + id)
              );
      }
      

      Query Methods with @Query annotation

      Repository with @query methods

      @Repository
      public interface AddressRepository extends CosmosRepository<Address, String> {
          void deleteByPostalCodeAndCity(String postalCode, String city);
      
          void deleteByCity(String city);
      
          Iterable<Address> findByPostalCodeAndCity(String postalCode, String city);
      
          Iterable<Address> findByCity(String city);
      
          Iterable<Address> findByCityIn(List<String> cities);
      
          Iterable<Address> findByPostalCode(String postalCode);
      
          Iterable<Address> findByPostalCodeInAndCity(List<String> postalCodes, String city);
      
          Iterable<Address> findByStreetOrCity(String street, String city);
      
          @Query("select * from a where a.city = @city")
          List<Address> annotatedFindListByCity(@Param("city") String city);
      
          @Query("select * from a where a.city = @city")
          Page<Address> annotatedFindByCity(@Param("city") String city, Pageable pageable);
      }
      
      public void testAnnotatedQuery() {
              addressRepository.saveAll(Arrays.asList(Address.TEST_ADDRESS1_PARTITION1, Address.TEST_ADDRESS1_PARTITION2));
      
              final List<Address> result = addressRepository.annotatedFindListByCity(Address.TEST_ADDRESS1_PARTITION1.getCity());
              assertThat(result).isNotNull();
              assertThat(result.size()).isEqualTo(1);
              assertThat(result.get(0)).isEqualTo(Address.TEST_ADDRESS1_PARTITION1);
          }
      

      Asynchronous API

      All corresponding methods are represented and results are very similar to its Synchronous counterpart. Async Client creation:

      import com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository;
      
      import info.hayslip.AlertHoarder.models.Alert;
      import org.springframework.stereotype.Repository;
      
      @Repository
      public interface AlertReactRepository extends ReactiveCosmosRepository<Alert, String> {
      // repo for alert
      }
      

      Known Limitations

      • Database/Collection is created as unknown, if the name is not retrieved from the properties file or if the name could not be resolved.