-
Notifications
You must be signed in to change notification settings - Fork 10
Document API
Astra and Stargate bring great innovation by allowing Apache Cassandra to store Documents like a document-oriented noSQL database. To cope with Cassandra data model constraints the document shredding function has been used.
As a Java developer you want to work with objects (entities) and let the SDK interact with the API performing operations you need Create, Read, Update, Delete and search.
AstraClient
andStargate
initializations have been detailed on the Home page. Moving forward the sample code will reuse those classes but do not initialized them.
Class ApiDocumentClient
is the core class to work with document. There are multiple ways to retrieve or initialize it.
// Option1. Given an astraClient
ApiDocumentClient client1 = astraClient.apiStargateDocument();
ApiDocumentClient client2 = client.getStargateClient().apiDocument()
// Option 2. Given a StargateClient
ApiDocumentClient client3 = stargateClient.apiDocument();
// Option 3. Constructors
ApiDocumentClient client4_Astra = new ApiDocumentClient("http://api_endpoint", "apiToken");
ApiDocumentClient client5_Stargate = new ApiDocumentClient("http://api_endpoint",
new TokenProviderDefault("username", "password", "http://auth_endpoint");
From now, in another samples, we will use the variable name apiDocClient
as our working instance of ApiDocumentClient
This class is the main unit test for this API and could be use as reference code
Stream<String> namespaces = apiDocClient.namespaceNames();
Related endpoint documentation can be found here
Stream<Namespace> namespaces = apiDocClient.namespaces();
Related endpoint documentation can be found here
Optional<Namespace> ns1 = apiDocClient.namespace("ns1").find();
apiDocClient.namespace("ns1").exist();
🚨 As of Today, the Namespace and Keyspace creations in ASTRA are available only at the DevOps API level.
// Create a namespace with a single DC dc-1
DataCenter dc1 = new DataCenter("dc-1", 1);
apiDocClient.namespace("ns1").create(dc1);
// Create a namespace providing only the replication factor
apiDocClient.namespace("ns1").createSimple(3);
🚨 As of today the namespace / keyspace creations are not available in ASTRA
apiDocClient.namespace("ns1").delete();
ℹ️ Tips
You can simplify the code by assigning apiDocClient.namespace("ns1")
to a NamespaceClient
variable as shown below:
NamespaceClient ns1Client = astraClient.apiStargateDocument().namespace("ns1");
// Create if not exist
if (!ns1Client.exist()) {
ns1Client.createSimple(3);
}
// Show datacenters where it lives
ns1Client.find().get().getDatacenters()
.stream().map(DataCenter::getName)
.forEach(System.out::println);
// Delete
ns1Client.delete();
The related Api Documentation is available here
// We can create a local variable to shorten the code.
NamespaceClient ns1Client = apiDocClient.namespace("ns1");
Stream<String> colNames = ns1Client.collectionNames();
CollectionClient col1Client = apiDocClient.namespace("ns1").collection("col1");
boolean colExist = col1Client.exist();
Optional<CollectionDefinition> = apiDocClient.namespace("ns1").collection("col1").find();
apiDocClient.namespace("ns1").collection("col1").create();
apiDocClient.namespace("ns1").collection("col1").delete();
ℹ️ Tips
You can simplify the code by assigning apiDocClient.namespace("ns1").collection("col1")
to a variable CollectionClient
CollectionClient colClient = apiDocClient.namespace("ns1").collection("col1");
colClient.exist();
//...
Class ApiDocument
is a wrapper to get your objects back but also their identifier. They are used for searches.
public class ApiDocument<BEAN> {
private final String documentId;
private final BEAN document;
}
Classes ResultPage
and its specialization DocumentResultPage
will be used to hold the paged results.
public class ResultPage<R> {
private final int pageSize;
private final String pageState;
private final List< R > results;
}
public class DocumentResultPage< DOC > extends ResultPage<ApiDocument<DOC>> {}
To simplify the code in the following samples we declared a CollectionClient
variable as follow:
CollectionClient colPersonClient = apiDocClient.namespace("ns1").collection("col1");
In our samples we will use the following Classes
:
public class Person {
private String firstname;
private String lastname;
private int age;
private List<String> countries;
private Address address;
//constructor..getters..setters
}
public class Address {
private String city;
private int zipCode;
}
// doc1 is the document Id in the collection
boolean docExist = colPersonClient.document("doc1").exist();
// Find returns an optional
Optional<Person> p = colPersonClient.document("doc1").find(Person.class);
// Define an object
Person john = new Person("John", "Doe", 20, new Address("Paris", 75000));
// As no id has been provided, the API will create a UUID and returned it to you
String docId = colPersonClient.createNewDocument(john);
// Define an object
Person john2 = new Person("John", "Doe", 20, new Address("Paris", 75000));
// Now the id is provided (myId) and we can upsert
String docId = colPersonClient.document("myId").upsert(john2, Person.class);
colPersonClient.document("myId").delete();
🚨 This operation can be slow. Every query to the API os paged. The method will fetch pages (limited the payloads size as much as possible) as long as they are and finally count the results.
int docNum = colPersonClient.count();
🚨 This operation can be slow. Every query to the API os paged. The method will fetch all pages
Stream<ApiDocument<Person>> colPersonClient.findAll(Person.class);
// Retrieve the first 10 items (page 1)
DocumentResultPage<Person> page1 = colPersonClient.findAllPageable(Person.class, 10);
// Retrieve the next 10 items (page 2)
DocumentResultPage<Person> page1 = colPersonClient.findAllPageable(Person.class, 10, page1.getPageState());
The document Api allows to search on any field of the document (!), we will have to create some clause where. In the rest API those look like: {"genre": {"$eq": "genre1"}, "year":{"$gte": 1989}}
in the SDK a dedicated bean with help is provided: SearchDocumentQuery
// Build query with the builder
SearchDocumentQuery query = SearchDocumentQuery.builder().where("age").isGreaterOrEqualsThan(21).build();
// Do the search
DocumentResultPage<Person> results = collectionPersonAstra.searchPageable(query, Person.class);
✅ Find part of a documents
// Retrieve a Scalar field
Optional<String> firstName = apiDocClient.namespace("ns1")
.collection("col1")
.document("myId")
.findSubDocument("firstname", String.class);
// Retrieve a list
System.out.println("Countries= "+ apiDocClient.namespace("ns1")
.collection("col1")
.document("myId")
.findSubDocument("countries", List.class)
.get());
// Retrieve an Object
System.out.println("Address/City = "+ apiDocClient.namespace("ns1")
.collection("col1")
.document("myId")
.findSubDocument("address", Address.class)
.get());
// Retrieve a scalar with depth=2
System.out.println("Address/City = "+ apiDocClient.namespace("ns1")
.collection("col1")
.document("myId")
.findSubDocument("address/zipcode", Integer.class)
.get());
✅ Update part of a documents
apiDocClient.namespace("ns1")
.collection("col1")
.document("myId")
.updateSubDocument("address", new Address("city2", 8000));
✅ Delete part of a documents
apiDocClient.namespace("ns1")
.collection("col1")
.document("myId")
.deleteSubDocument("address");
🏠 Home | Document | Rest | Native Drivers | GraphQL | gRPC | Astra Devops |