An effortless database exposes the queries developers need to build their applications. Though we maintain multiple databases across our multiple data centers, we expose that query-ability via a single API.

Today’s applications need those many ways to query data, but they also require flexibility to update it. Developers using Orchestrate for their database can now use a powerful update syntax that allows for partial updates, data merges, and operations on a subset of an item’s data.

The JSON Object store is the foundation of our NoSQL solution. Previously, the entire contents of an existing document needed to be sent with each update. To change a single field, developers needed to read down the latest version of a document, make the change to the appropriate field, then send back the changed document. For most situations, this is fine, but our customers continued to discover use cases for partial updates. This feedback encouraged us to release this pliable new feature.

There are two ways to update a portion of the fields in an item, both shown in the video above:

  • Patch Merge: Send a partial JSON document to merge with an existing document (replacing values of existing fields and adding any new fields)
  • Patch: Send a series of one or more operations as a JSON array

Patch Merge

Patch Merge acts very much like storing a standard Orchestrate JSON Object. The only differences are that you use the HTTP PATCH verb (POST also accepted with a Content-Type header of ‘application/merge-patch+json’) and only pass the fields you want to update.

For example, let’s say you had a document that described a restaurant in your neighborhood, with all sorts of data: address, phone number, website, geo coordinates, and more. You receive some new data for the restaurant and you need store it into Orchestrate. Maybe you have its open hours and it moved its website off of GeoCities.

curl -i "https://api.orchestrate.io/v0/restaurants/labonita" \
  -XPATCH \
  -H "Content-Type: application/merge-patch+json" \
  -u "$api_key" \
  -d '{"website": "http://labonitarestaurant.net/", "hours": "10 AM-10 PM"}'

Patch Merge will update the website field, add the hours field and leave the rest of the document the same. As a best practice, you can use an If-Match header to perform a conditional PATCH using the reference, or ref, of the most recent version of the document you have. Using a conditional PATCH avoids conflicts from multiple clients making writes around the same time.

Patch

Patch is useful for manipulating single fields, incrementing counters or performing some manipulations not supported by Patch Merge. For example, you can remove, move and copy fields, or even add elements to an existing array.

curl -i "https://api.orchestrate.io/v0/landmarks/eiffel" \
  -XPATCH \
  -H "Content-Type: application/json-patch+json" \
  -u "$api_key" \
  -d '{"op": "replace", "path": "name", value: "La tour Eiffel"}'

The above example replaces the current value of the name field in the eiffel key of the landmarks collection with “La tour Eiffel.”

As a best practice, you can include a test operation to only perform the replace if the name is currently stored with an expected value. Using the test operation can identify situations where multiple clients may be attempting writes at around the same time.

curl -i "https://api.orchestrate.io/v0/landmarks/eiffel" \
  -XPATCH \
  -H "Content-Type: application/json-patch+json" \
  -u "$api_key" \
  -d '[{"op": "test", "path": "name", value: "Eiffel Tower"},
      {"op": "replace", "path": "name", value: "La tour Eiffel"}]'

To feel extra secure with your patch, you can use a conditional PATCH, as in the Patch Merge example.

Here are examples of all of the operations currently supported by Patch:

{ "op": "test", "path": "age", "value": 28 }
{ "op": "remove", "path": "birth_place.country" }
{ "op": "add", "path": "birth_place.city", "value": "New York" }
{ "op": "replace", "path": "birth_place.state", "value": "New York" }
{ "op": "move", "from": "first_name", "path": "deprecated.first_name" }
{ "op": "copy", "from": "full_name", "path": "name" }
{ "op": "inc", "path": "age", "value": 1}

The default value for increments is 1 and any numeric value (including negatives for decrement) is acceptable.

Rather than re-inventing the wheel, our engineers used existing RFCs (6902 and 7386) as a basis for Patch and Patch Merge. Together, these partial update features provide you with more flexible ways to write data to Orchestrate.

A big thanks goes out to the developers who provided feedback on UserVoice. This ticks off yet another top-requested feature, so keep the votes coming.