Less-well-known features of Multilingual Engine: Document API

Many developers like the simplicity and flexibility provided by specialised document databases. These systems offer a lot of freedom when it comes to writing applications. If you don’t like SQL, a document API provides another way to persist data.

There is no better or worse approach. Developers should be empowered to use the technology they are most comfortable with unless the choice of technology compromises other important application features like scalability, availability, security to mention just a few.

Modern databases are great in the way they offer choice to developers.

Document APIs are also present in modern databases

For a very long time, Oracle has provided a document API named SODA—short for Simple Oracle Document Access. Oracle also supports the Mongo DB protocol in the form of Oracle Database API for MongoDB. In addition to these two, Oracle Database 23ai introduced JSON Relational Duality Views, which is a really, really interesting feature for developers.

But let’s get back to SODA. SODA offers drivers for popular languages like JavaScript, Python, and many others. In addition to the aforementioned client-side drivers, developers have another option: using a document API in server-side languages.

Document API can be used by server-side code

Running code on the database server has many advantages. For starters, you are guaranteed not to suffer from latency introduced by round-trips from client to server. Others have been documented elsewhere if you are interested. Server-side languages, however, aren’t the most fashionable way to code. This is where a new feature in Oracle Database 23ai on Linux might help.

Oracle Database 23ai introduced Multilingual Engine(MLE), offering another server-side programming language: JavaScript. JSON and JavaScript go hand in hand, and it is very easy to use a document API with MLE.

Let’s assume a typical use case where an application POSTS a JSON payload to the backend for storage. This is straight-forward with Oracle technology:

  • You use Oracle REST Data Service (ORDS) as your API endpoint. ORDS receives all those GET, PUT, POST, DELETE requests. ORDS makes your lives easier by providing a lot of functionality you’d otherwise have to write yourself.
  • ORDS is connected to the database. It takes care of routing the API requests to the relevant object in the database. That includes JavaScript code, tables, views, PL/SQL, almost anything can be ORDS-enabled.
  • By routing an API endpoint to JavaScript, you can make use of a document API.

Let’s have a look at a piece of JavaScript code using the SODA API to persist JSON provided by a POST request. From the code alone, it is not possible to tell if this runs on the client or server.

/**
 * Retrieve a purchase order by ID
 * @param {number} id the purchase order's ID
 * @returns {object} the purchase order as retrieved from the database
 * @throws an exception if the collection cannot be opened for reading
 */
export function getPurchaseOrder(id) {
	const collection = soda.createCollection("exampleCollection");

	if (collection === null) {
		throw new Error("failed to open the collection for reading");
	}

	const data = collection.find().filter({ _id: id }).getOne().getContent();

	return data;
}

/**
 * Process a purchase order
 * @param {object} po the purchase order to process
 * @throws an exception if the validation fails
 */
export function savePurchaseOrder(po) {

	const collection = soda.createCollection("exampleCollection");

	if (collection === null) {
		throw new Error("failed to open the collection for reading");
	}

	// simulate some kind of validation. Assume, for example,
	// you need at least one line item and a customer name
	// this would be more sophisticated in real life.
	if ("customer" in po && po.lineItems.length > 0) {

		collection.insertOne(po);
	} else {
		throw new Error("error storing the purchase order: document failed validation");
	}
}

The lines highlighted present those document API calls. If you have used a document API before, these are probably quite familiar. Oracle JavaScript Developer’s Guide features an entire chapter on the SODA API if you would like to explore it more.

Testing

Once this JavaScript module is loaded into the database, and exposed as GET and POST handler by ORDS, you can call it from any client you like. Since curl is ubiquous, it’s used here. But this is equivalent to your Angular, React, Vue, Django, Flask, J2EE application: they’d all make the same REST call via fetch() or equivalent call.

Insert a new JSON first:

curl --json '{
"_id": 1,
"address": {
"city": "Frankfurt",
"country": "DE",
"post_code": "60311",
"street": "Neue Mainzer Strasse 46-50"
},
"customer": "some customer",
"lineItems": [
{
"item_no": 1,
"product": "abc",
"quantity": 10
},
{
"item_no": 2,
"product": "xyz",
"quantity": 20
}
]
}' https://localhost:8181/ords/martin/api/orders/

After which you can query it:

curl https://localhost:8181/ords/martin/api/orders/1

The output is the same as the input, which is why it’s not shown here.

Summary

The best thing about modern IT is choice. Developers can pick whichever solution they are most comfortable with for their projects. As you can see from the code example in this article, modern converted databases can support a great many workloads in many languages and formats.