Persevere and CouchDB are both new JSON-based storage systems, and have been receiving increasing focus. It may be informative to those interested in these new technologies to discuss the differences between these new database systems and what types of applications each is best suited for. While Persevere and CouchDB share an extremely similar JSON HTTP/REST interface and object structured data storage, there are important distinctions. Each of these different tools has a different target audience, and despite my obvious bias being the developer of Persevere, I hope to give at least some semi-objective differentiations between these tools.
|Project||Description/Primary Use Case|
|CouchDB||A JSON document based database for storing hierarchical object-style data structures using an HTTP interface with ACID lockless operation. This is primarily intended for being used by server-side technologies, and is not focused on direct browser access.|
We will now take more in-depth look at the differences between Persevere and CouchDB (focusing on CouchDB due to it’s similarity to Persevere and its popularity).
An essential aspect of any database is its querying capabilities, and Persevere is differentiated from CouchDB by its ability to handle ad-hoc parameterized queries. Traditional relational databases utilize SQL for querying. SQL is inappropriate for a JSON-based database, the data structures are completely different, and for Ajax applications that are leveraging a HTTP interface directly from the browser, SQL is hopelessly insecure. CouchDB uses a view model which acts as an ongoing incremental map-reduce function, providing a constantly updated view of the database. From the HTTP interface different views can be accessed and data can be retrieved by key/index as well. The view model is well-suited for statically definable queries; job-style operations. On the other hand, Persevere uses JSONQuery, an extended version of JSONPath, as its query language which can be used to retrieve data from the database directly in the HTTP/REST interface. The difference here is that you can dynamically create a query with any arbitrarily complex expressions and any values. The workhorse of most applications is parametrized queries and these can easily be created with JSONQuery expressions and handled by Persevere.
// create a new object in a table/class var myObj = new MyClass(); // set a property, automatically persisted to the database myObj.foo = "bar"; // this will return true myObj instanceof MyClass
Security and access control have been key features of Persevere from the start of the project; CouchDB also recently added access control. CouchDB provides two global access levels: Administrator and Reader. Persevere provides much finer-grained access control, it is possible to assign different access levels for different users to different tables, and even to different specific objects. Persevere’s security system is capability-based, and capabilities can be created that encompass a set of access levels to different objects or tables in the system. These capabilities can be individually granted to different users. CouchDB and Persevere both also support more programmatic control of security during object validation to handle more complex logic for access decisions.
Persevere provides an API for authentication from the web, and supports maintaining authentication with cookies (no manual manipulation of the requests is required).
Rich Data Structures
CouchDB is explicitly schema-free, and no constraints are applied to documents. Persevere provides a flexible evolutionary approach to schemas, tables start schema-free, but schema constraints can be applied as desired to existing tables to create integrity guarantees. Partial constraints (to some properties) can be defined and modified at any point in time allowing any level of flexibility or integrity desired.
Scalability and clustering has been one of the primary focuses of CouchDB: its name is an acronym for Cluster of Unreliable Commodity Hardware. CouchDB is certainly more mature in this category with its advanced clustering capabilities and heavy focus on extreme scalability. Clustering is certainly on the road map for Persevere. The REST architecture is designed for scaling across multiple machines and Persevere is well suited for adding this capability. In fact, with Persevere’s Comet notification system, clustering can and should be implemented almost entirely with its standard documented HTTP interface.
With Persevere, it is possible to have a real-time view of data by subscribing to objects and receiving notification of changes. This capability is specifically designed for web applications. Notifications can be received from the browser using the REST Channels Comet interface. Persevere’s Comet capabilities are not limited to data changes, but any type of method call can serve as event for broadcast to clients. Persevere also supports Bayeux and its PubSub system. These Comet capabilities are exclusive to Persevere, and CouchDB has nothing that is similar.
Persevere and CouchDB both provide isolated transactions with lockless operation (objects are never locked). With CouchDB, each request corresponds to a single transaction, and by default Persevere behaves the same way. Persevere and CouchDB both support multi-operation transactions, and it is also possible to do multiple actions in one isolated transaction. For example, you could create a new object, update another object, and delete a third and then commit all three actions as a single transactional operation. CouchDB provides this capability through “bulk updates”. Persevere handles multiple action transactions by allowing multiple HTTP requests to be grouped together in a single transaction.
CouchDB provides the advantage of full ACID compliance. Persevere currently provides consistency, isolation, and durability, but is not truly atomic at this time. True atomicity is intended to be implemented in the future.
All object updates in CouchDB are preconditioned on providing the correct previous version number of the object that is being modified (optimistic concurrency). If the version number does not match, it is assumed to have been modified elsewhere and the operation will fail. Persevere provides a more flexible precondition system. Updates to objects can be made without preconditions to make it easier to get started. Preconditions can then be added, and any type of expression can be used as a precondition. In many situations predicating an update on a version number is a naive. Often an update is performed on the basis of various other, possibly more complex, object states. For example, if one is operating a translation service in order to translate text from English to Japanese, the application may wish to update the Japanese object on the precondition that the English version has not changed (rather than on the condition of the Japanese object not changing).
From the browser, cross-domain requests require special techniques due to the same-origin policy that is applied to the XMLHttpRequest object. Persevere supports both JSONP (scripts with callbacks) and the window.name protocol for providing data for cross-domain web clients. CouchDB does not provide a facility for handling cross-domain requests.
Legacy Data Sources
Another unique capability of Persevere is that it will not only work with the default internal object database, but it can also be used to connect to existing SQL databases and even other remote RESTful HTTP servers as well. The configuration files are treated as data sources in the pluggable data source layer as well.
Binary/non-JSON Content Support
Both Persevere and CouchDB support the storage of non-JSON content in their databases. CouchDB treats non-JSON data as “attachments” within the JSON structure. On the other hand, Persevere provides a “File” table which holds the non-JSON entities, and with Persevere’s referencing capabilities, these entities can easily be included within any object in the system. Persevere builds on the REST architecture and allows these files to be used as an alternate representation of existing JSON objects. Content negotiation can then be used to retrieve these alternate format types for resources in Persevere. For example, one could define a JPEG image as an alternaten representation of a Person object in Persevere. To further support browser-based interactivity, Persevere supports the upload of files using standard browser forms. Files can be added and retrieved directly from browser.