HyperDex recently added support for storing and querying schema-less JSON documents. This is a big step for the next-generation database that pioneered many new techniques for efficient, consistent, fault-tolerant data storage -- it is not only a fast key-value store, but also a document store now. You can store JSON documents and query them by their properties, nested arbitrarily.
The latest HyperDex release also sports Node.js bindings. Combined, the pair make a powerful combination that's easy to work with.
Let's see how these new features work in practice. To get started, you may need to download HyperDex and follow the easy installation instructions for your platform. Once you have HyperDex installed, you can quickly setup a running cluster by running the coordinator:
$ hyperdex coordinator -f -l 127.0.0.1 -p 1982
followed by the storage daemon to store data:
$ hyperdex daemon -f --listen=127.0.0.1 --listen-port=2012 \
--coordinator=127.0.0.1 --coordinator-port=1982 \
--data=/path/to/data
We now have a HyperDex cluster ready to serve our data. Finally, let's create a new space on the cluster. Spaces in HyperDex are like "tables" in traditional SQL stores, or "collections" in MongoDB. In this example, let's create a space suitable for storing social network profiles.
$ hyperdex add-space << EOF
space profiles
key username
attribute
document profile
EOF
Consider a social networking application that stores each user's profile as a document in HyperDex. Users which provide very little information to the social network will have a relatively sparse profile. The bare minimum profile could look like this:
{"name": "John Smith"}
You can store this profile in HyperDex by connecting to the cluster and simply "putting" the user's profile. Here's a sample program that does just that:
hyperdex_client = require('./hyperdex-client')
c = new hyperdex_client.Client('127.0.0.1', 1982)
c.put('profiles', 'jsmith1', {profile: {name: 'John Smith'}},
function(err, success) {
if (err) { /*an error ocurred; look at err for details*/}
console.log("The \"put\" operation returned: " + success);
});
If you paste the above code into a file, and run it with node demo.js, you'll see the following:
$ node demo.js
The "put" operation returned: true
The "put" operation completes and then the program exits. True to well-accepted Node practice, HyperDex hooks into the Node event loop, ensuring that operations are performed asynchronously. This enables you to do other things while waiting for the HyperDex operations to complete.
Let's flesh out our social networking example some more. Consider a user named Jane Doe who has fleshed out his profile some more, and has established a friendship with John Smith. You could encode these relationships with the following code:
hyperdex_client = require('./hyperdex-client')
c = new hyperdex_client.Client('127.0.0.1', 1982)
c.put('profiles', 'jd', {profile: {name: "Jane Doe",
www: "http://example.org",
email: "doe@example.org",
friends: ["John Smith"]}},
function(err, success) {
if (err) { /*an error ocurred; look at err for details*/}
console.log("The \"put\" operation returned: " + success);
});
The profile for Jane Doe looks just like a Javascript object because it is a Javascript object.
Searching over documents is almost as easy. For example, to retrieve the objects for all people named Jane Doe, you can do a search on profile.name to retrieve all such objects:
hyperdex_client = require('./hyperdex-client')
c = new hyperdex_client.Client('127.0.0.1', 1982)
c.search('profiles', {profile: {name: "Jane Doe"}},
function(err, obj, done) {
if (err) { /*an error ocurred; look at err for details*/}
if (obj !== undefined) { console.log("retrieved %j", obj); }
if (done) { console.log("the search is done"); }
});
Here's what will happen when you run this script:
$ node demo.js
retrieved {"username":[106,100],"profile":{"name":"Jane Doe","www":"http://example.org","email":"doe@example.org","friends":["John Smith"]}}
the search is done
The callback will be called once for each object, and then once at the end of the search. You can see that the object returned is the one that we've stored.
We've only scratched the surface of Javascript support in HyperDex. For more information consult the following resources: