About Rui Quelhas

MySQL Connector/Node.js lead developer.

MySQL Document Store CRUD Quick Start

This post serves as a quick start guide on how to use the MySQL Document Store with the official Node.js connector. It mainly highlights how easy it is to leverage CRUD-style operations and getting up and running with the X DevAPI.

Before you jump in

Make sure you have Node.js 7.6.0 (or higher) and MySQL 8.0.11 (or higher) installed on your machine.

Setting up your Node.js project

First, using the command line, let’s start by creating a directory for our sample application.

Create a package.json manifest file using the following command:

Next, install the MySQL Node.js Connector from npm:

Starting the MySQL Server

For additional tips on how to install and secure your MySQL server, check the documentation.

  1. Download (if you have not yet) MySQL 8.0
  2. Install and set up a basic (and insecure) server process.

We are using  --initialize-insecure here for the sake of simplicity, however, make sure you use --initialize  (and set up users and privileges accordingly) on production environments and/or “real-world” scenarios.

Connecting to MySQL

Create a new app.js file and write the following code for establishing a connection to the MySQL server using the myproject database/schema (which will be created by default).

The getSession method should return a JavaScript Promise which resolves with a Session object containing the connection details or fails with a Node.js Error if the connection could not be established.

Run the app using the following command:

You should be able to see a Successful server connection  message printed in the console.

Inserting documents

Use the following code to create (or re-use if it exists) documents  collection and add three new documents to it.

The add method returns a Promise which resolves with a Result  object containing details such as:

  • the number of items affected by the operation
  • a list of document _ids auto-generated by the server
  • any server-side warnings resulting from the operation

Add an insertDocuments call in the existing main function like the following:

Running the app should yield the following output:

Retrieving all documents

You can use the following code to retrieve all the existing documents in the collection.

To collect and process records from the result set, you should provide a callback in the execute method.

Use the findDocuments method in the main function.

Finding documents with a given criteria

You can narrow down the results by specifying a query criteria like the following:

The result set will now include just the documents containing 'a': 3.

Updating documents

To modify an existing document i.e. updating specific properties or adding new ones, you can also provide a criteria (or true to modify all) for the operation.

Update the main function to use the updateDocument method like the following:

Removing documents from a collection can also be done based on a given criteria (or true  to remove all). The following code removes the document where the field a is greater than 2.

To test this behavior, call the removeDocument method in the main function.

Creating secondary indexes

You can create a secondary index for any property of a document in a collection using the following code:

Just like before, update the main function to use the createIndex method.

Wrapping up

This is just an overview of some of the features and API methods for taping into the MySQL document store using the Node.js connector and the X Dev API. For additional details, check the following links:

Introducing Connector/Node.js for MySQL 8.0

As you may have heard, MySQL 8.0 is now officially GA, and it comes with a bunch of additional goodies. Among those is the brand new Connector/Node.js, which is the official MySQL driver for Node.js and, currently, the only one with support for the latest server versions and features (such as the MySQL document store).

Here’s a rundown of what’s available:

  • Out-of-the box support for MySQL 8.0
  • Document-store API as a first-class citizen
  • TLS/SSL and SHA256 authentication
  • Fluent API with support for flexible parameters
  • Semantic methods to encode common CRUD operations
  • Modern Node.js asynchronous interface based on Promises
  • Abstractions for common database development tasks
  • Transactions, savepoints and row locking

MySQL 8.0

Connector/Node.js is currently the only driver in the Node.js ecosystem that works out-of-the-box with the latest MySQL 8.0 series and implements the brand new X Protocol and X DevAPI, which unlocks exclusive server features such as the MySQL document store.

In a nutshell, the X Protocol is based on the Google Protocol Buffers serialization format, and provides a common interface for a different set of official connectors to bridge into the MySQL server via the X plugin, which contains the server-side implementation of the document store and a surrounding scaffolding ecosystem including things like common CRUD expression trees, bound parameters, or expectations and conditions for statement pipelining.

The X DevAPI is the common client-side API used by all connectors to abstract the details of the X Protocol. It specifies the common set of CRUD-style functions/methods used by all the official connectors to work with both document store collections and relational tables, a common expression language to establish query properties such as criteria, projections, aliases, and a standard set of additional database management features for handling things like transactions, indexes, etc.

The fact that most of these features share the same format and API between connectors, makes the X DevAPI a perfect fit for mordern polyglot development environments such as microservices, and the fact that they are based on a well-documented format allows advanced users to extend client-side implementations and build new middleware components or extensions tailor-made for their use case.

Although, there are (most of the times) matching client APIs to work with relational tables, this overview will focus mostly on document-store related features. Check the official Connector/Node.js documentation or the X DevAPI user guide to get the full picture.

Secure by default

With Connector/Node.js, SSL/TLS is enabled by default for server TCP connections and, additionally, the server identity can be validated against a given certificate authority (CA).

Of course you can explicitely override this behavior (at your own peril).

Local Unix sockets don’t use SSL/TLS since they don’t really benefit much from that level of security. At the same time, that removes the possibility of any additional performance overhead caused by the SSL/TLS handshake.

In the authentication realm, besides the traditional SHA1-based server authentication plugin, Connector/Node.js also supports the latest secure authentication plugins based on SHA-256. Of course you can always use your own custom server plugins, as long as the authentication data can be sent using one of the existing client-side authentication mechanisms (in the simplest form, via plain text).

Additional details about Connector/Node.js security can be found here.

Fluent API

The public API flows nicely from a single getSession()  method. Whereas, when it comes the point of creating and issuing database operations, you get a nice fluent query builder where those operations are encapsulated in specialized and specific methods, which, compared to using raw SQL statements, brings benefits such as:

  • more readable, maintainable (and even testable) code
  • better tooling integration
    • scaffolding for code refactoring
    • text-editor (or IDE) hints and auto-completion
  • smaller SQL injection surface area
  • common standard between different programming languages and environments

Most public API methods provide alternative input handling flavors:

  • multiple individual arguments
  • a single array of arguments
  • an object with named properties (where it applies)

Promise-based asynchronous tasks

Being a good Node.js citizen, Connector/Node.js encapsulates all blocking I/O operations with asynchronous methods. Each method that sends a message to the MySQL server is expected to return a JavaScript Promise , which resolves to the specific result or fails with an error. This pattern also unlocks other platform abstractions such as the async/await  syntax, making it even more flexible for the user than just using traditional error-first callbacks.

So, after building a query, it can be sent to the server via the execute()  method. In turn, the method receives an optional callback as argument, which runs for each element in the result set. When using relational tables, an additional callback function can be used to tap into the given column metadata.

Other methods, such as the ones that operate on a single instance of a connection, database object (be it a schema, table/collection, row, document, etc.) will return a Promise  by themselves (dropping the extra call to execute() ). Some examples:

  • mysqlx.getSession()
  • session.getSchemas()
  • session.createSchema()
  • schema.getCollections()
  • schema.createCollection()
  • collection.getOne()
  • collection.addOrReplaceOne()
  • collection.replaceOne()
  • collection.createIndex()

Data consistency

With MySQL 8.0, you get session-level consistency and document-level isolation via multiple database constructs, such as transactions, savepoints and row locking. This allows to encapsulate a set of operations (particularly DML) encompassing multiple documents or collections in a single atomic procedure within a given session.

Connector/Node.js provides APIs to create, commit or rollback a transaction as well as to create, release or rollback to an intermediate savepoint within that transaction.

In the presence of concurrent transactions, the isolation level of each operation within the transaction, operating on a given document, can be determined using row locks.

Raw SQL interface

If you are looking for a feature that is still not available on the X DevAPI, or simply something that does not fit the CRUD model, you can always resort to plain old SQL.

Getting Started

If you want to use Connector/Node.js in your own project or just want to play around with, download the latest version from npm:

New releases DO NOT follow semantic versioning, so, to avoid being affected by breaking changes, make sure you use --save-exact  when pulling the package, particularly if you don’t have npm-shrinkwrap.json  or package-lock.json  files locking down your project’s dependencies.

If you are an advanced user, being an open source project, the code is hosted on the official GitHub repository and contributions are welcome, either in the form of bugs ( Connector for Node.js  category) or pull requests.

Up and Running

Assuming you are running MySQL 8.0 with the default configuration and Node.js v8.0.0  or later (for async/await  support), using Connector/Node.js and the MySQL document store in your project is as simple as follows:

These are just some of the highlights. Make sure you check out the official Connector/Node.js documentation or the X DevAPI user guide for usage examples and even more details on how to get started.

Please give it a try! Your feedback is more than welcome.