The Java OJAI DocumentStore and Query APIs provide
the ability to track writes to JSON tables. Use these APIs to ensure your application reads
recent writes on JSON tables with secondary indexes.
You should use this feature if it is important for your query results to reflect synchronized data between a JSON table and its secondary indexes. Because HPE Ezmeral Data Fabric Database updates secondary indexes asynchronously, it is possible for a JSON table and its secondary indexes to become out-of-sync while the index update is in progress.
For example, consider the following scenario:
address field that is a nested document with
a zipCode subfield. zipCode.zipCode. You want your query result to reflect the updates from earlier in your application. To
achieve this, use the DocumentStore and Query APIs that
enable you to retrieve up-to-date information from the index. The APIs synchronize write
operations on the JSON table with read operations on a secondary index.
See Asynchronous Secondary Index Updates for more information about index updates.
The OJAI DocumentStore and Query interfaces provide the
following methods to support this functionality.
DocumentStore.beginTrackingWritesDocumentStore. The method takes an optional
previousWritesContext parameter. If you specify this parameter, the
tracking uses that context as the base state.DocumentStore.endTrackingWritesDocumentStore and
returns a writesContext. Use this context to ensure that writes are
visible to later queries. You can use the context across
DocumentStore objects in the same, as well as different, client
processes, when the stores refer to the same JSON table. For example, you can pass the
writesContext returned by one DocumentStore to a
second DocumentStore, to begin write tracking on the second
store.DocumentStore.clearTrackedWrites
DocumentStore
instance.Query.waitForTrackedWriteswritesContext parameter for this query. A
writesContext allows this query to "see" all the writes that
happened inside the writesContext of a
DocumentStore. For the complete API, see Java OJAI Client API.
A complete code example is available on github at OJAI_013_ReadYourOwnWrite.java. The following are code snippets from that example. Each step contains links to corresponding lines of code in the github example:
/demo_table:// Create an OJAI connection to MapR cluster
final Connection connectionNode1 = DriverManager.getConnection("ojai:mapr:");
// Get an instance of OJAI DocumentStore
final DocumentStore storeNode1 = connectionNode1.getStore("/demo_table");
// initiate tracking of commit-context
storeNode1.beginTrackingWrites();zipCode of an existing user and insert a new user in
/demo_table:// issue a set of mutations/insert/delete/etc
storeNode1.update("user0000", connectionNode1.newMutation().set("address.zipCode", 95110L));
storeNode1.insertOrReplace(connectionNode1.newDocument(
"{\"_id\": \"user0004\", \"firstName\": \"Joel\", \"lastName\": \"Smith\", \"age\": 56, \"address\": {\"zipCode\":{\"$numberLong\":95110}}}"));final String commitContext = storeNode1.endTrackingWrites();The
call also returns a commitContext.
commitContext from step
3:/*
* Next section of the code can run on the same or on a different node,
* the `commitContext` obtained earlier needs to be propagated to that node.
*/
// Create an OJAI connection to MapR cluster
final Connection connectionNode2 = DriverManager.getConnection("ojai:mapr:");
// Get an instance of OJAI DocumentStore
final DocumentStore storeNode2 = connectionNode2.getStore("/demo_table");
// Build an OJAI query and set its commit context with timeout of 2 seconds
final Query query = connectionNode2.newQuery()
.select("_id", "firstName", "lastName", "address.zipCode")
.where("{\"$gt\": {\"address.zipCode\": 95110}}")
.waitForTrackedWrites(commitContext)
.build();The
query filters on the indexed subfield address.zipCode. The
commitContext ensures that the query result includes the changes made
in step 2.