MarkLogic for JavaScript Developers

MarkLogic is a database. In particular, it is a distributed document database. It stores and indexes JSON, XML, and RDF natively. This is great for JavaScript developers. Persisting JSON in your database, saves you from having to maintain brittle and error-prone translations between your code and your data. It also allows you to share data models and the code that processes them throughout your stack.

Developers writing JavaScript applications with Node.js can use the MarkLogic Node.js Client API to access a MarkLogic cluster. It is a fully asynchronous, fluent API for reading and writing data, with conveniences for building queries and working with streams. You can install it from npm (npm install marklogic) and require it from your Node app. For example,

Remote data access is cheap, but not free, even in Node.js. Some code needs to run closer to the data.

"Remote calls are more expensive than in-process calls, and thus remote APIs need to be coarser-grained, which is often more awkward to use. If you need to change the allocation of responsibilities between components, such movements of behavior are harder to do when you’re crossing process boundaries."

This is why MarkLogic also provides a full JavaScript runtime in the database itself. That’s right, with MarkLogic you can write JavaScript that runs in a MarkLogic cluster, close to the data. You can develop, test, and version JavaScript for MarkLogic, just like you would any other JavaScript, using the tools and libraries you’re familiar with. You can invoke MarkLogic JavaScript modules from the Node.js Client API (or the Java Client API), or even publish your own web services using the built-in HTTP server.

"But I thought it was bad practice to put business logic in my database? Isn’t that the job of the application tier?"

Transactions run inside the database because they’re difficult to do correctly in the application tier and performance at scale counts. Shouldn't you be able to push other concerns down to the data tier as well? With MarkLogic Server-Side JavaScript, you’re not mixing application and persistence concerns, but rather deploying code to where it can be most effective.

In a relational database, you'd write a stored procedure or some PL/SQL or T-SQL. These languages require special skills and dedicated tools. In MarkLogic, you build in-database logic with JavaScript, a language that just about everyone on your dev team already knows. Your JavaScript runs in an embedded instance of Google’s V8 engine—the same engine that Chrome and Node.js use. We've wired things up such that a Server-Side JavaScript module has access to all of the rich built-in capabilities implemented in C++ in the database engine through a set of friendly, fluent JavaScript APIs. MarkLogic takes care of all of the tricky isolation and lazy evaluation under the covers, so developers can focus on their code, not distributed transactions.

The code below illustrates the most basic concepts, inserting, querying, and updating JSON in MarkLogic. For more details on the rich set of APIs available, consult the expansive API and usage docs.

Insert

To play along at home, open up Query Console on the host where you installed MarkLogic. Paste the following query into your empty workspace and run it to create some documents.

This query inserts two new JSON documents into the database. In this case, each document represents a character from the popular American television show, "The Muppets". As such, the code adds them to the muppets collection, so you can easily ask for all Muppets later.

All inserts and updates happen transactionally. Thus, if there’s an error midway through the execution of your code, you can be assured that any changes that were initiated will automatically be rolled back. You can try this by throwing an Error somewhere in the code, such as in the second iteration of the loop.

Query

Now that the JSON documents are stored in the database, you can query them.

This query returns a report of all the documents that match the where(), similar to how the WHERE clause works in a SQL query. In this case, the query uses query by example (qbe) to match a representative instance.

Not only do you get back the matched documents themselves, but also some additional information about the match, much like the statistics you’d get from a search engine. The ability to combine database and search engine-style queries is a key advantage of MarkLogic.

Update

As a database, you also need to be able to update documents. In this case, the example updates one particular document to add a new demeanor property, using the query above.

Documents in the database are stored as trees of Nodes. This generalizes across JSON and XML. As an optimization for performance and consistency, Nodes are immutable. This means that when you get a JSON document out of the database for update, the pattern is

  1. Convert the document (Node instance) to a plain old JavaScript object (.toObject())
  2. Update the object’s properties, just as you would any mutable JavaScript object (obj.demeanor = 'cantankerous')
  3. Then finally save it back to the database as a new Node, replacing the existing one (xdmp.nodeReplace(result.document, obj)).

Delete

Finally, clean up by removing the documents in the muppets collection that you just created.

Comments

  • Could I apply this script code from my client api java?
    • Yes, you can write <a href="http://docs.marklogic.com/guide/java/resourceservices#chapter">REST API extensions using Server-side JavaScript</a>, which you can then call from the Java Client API.