Agile data modeling involves a collaborative, iterative, and incremental approach to data modeling. In this article, we discuss how MySQL Document Store could be used for agile data modeling.
Up until the 2nd half of the 2000s, before the NoSQL databases, the only option was relational databases (RDBMS).
Problem
A RDBMS table has a pre-defined number of named columns with fixed data types. The data has to be structured and all rows of data must include data for each row, albeit null values. As the data model evolves, the data definition could become obsolete quickly. DDL does provide statements to add/remove/modify columns but it could be cumbersome to make such changes frequently.
Solution
Agile data modeling involves a collaborative, iterative, and incremental approach to data modeling. MySQL 5.7+ added support for the JSON data format, which is a flexible, schema-less data format. We also discuss how the X DevAPI introduced with the X protocol plugin enables storing data as JSON documents in collections. The X DevAPI may be accessed from the MySQL Shell and Connectors. In this article we discuss how MySQL Document Store could be used for agile data modeling.
Getting Set Up
We have used MySQL 8. Additionally, you would need to install the X Plugin, which provides the X Dev API. The X Plugin is installed by default with MySQL 8.0.37. Verify by running the following command to list installed plugins, and the mysqlx plugin should be listed.
C:\Program Files\MySQL\MySQL Shell 8.0\bin>mysqlsh -u root --sqlc -e "show plugins"
Please provide the password for 'root@localhost': *****
Name Status Type Library License
binlog ACTIVE STORAGE ENGINE NULL GPL
…
mysqlx_cache_cleaner ACTIVE AUDIT NULL GPL
mysqlx ACTIVE DAEMON NULL GPL
Your First Data Model
Let’s say someone asked you to develop a data model for a magazine catalog. You come up with a rather simple magazine catalog with only one attribute, magazine name. For the data model you create a JSON collection in the MySQL Document store. A collection is a container for JSON documents. The following JavaScript code in MySQL Shell establishes a user session, creates a collection in the test database, and adds a document with only one attribute.
First, require the mysqlx extension.
var mysqlx = require('mysqlx');
Create a Server Session. Note that the X Protocol port is 33060.
var s1 = mysqlx.getSession( {
host: 'localhost', port: 33060,
user: 'root', password: 'mysql'} );
Get a database object.
var db = s1.getSchema('world');
Create a new collection.
var coll1 = db.createCollection('magazine_catalog');
Add a document.
coll1.add({ name: 'PHP Magazine', age: 19 }).execute();
As the output indicates, one document gets added.
MySQL JS > coll1.add({ name: 'PHP Magazine', age: 19 }).execute();
Query OK, 1 item affected (0.0838 sec)
Developing the Data Model
Perhaps you ask others to develop the data model further. A collaborative, iterative, incremental approach is what makes such a data modeling methodology agile. A second developer reviews the first data model and finds it rather lacking; not much information on who the publisher is, the publication frequency, the category of the magazine (general, news, fashion, technology, etc.), and the media type (print, digital). The second developer creates a collection object for the existing collection magazine_catalog
, and adds a second document.
Get a collection object.
var coll1 = db.getCollection('magazine_catalog');
Add a document.
MySQL JS > coll1.add({name: 'Java Magazine',publisher: 'Oracle Publishing',frequencyPerYear: 6, category: 'Information Technology', mediaType: 'Print' }).execute();
Query OK, 1 item affected (0.1194 sec)
A third developer adds three other useful attributes: published since, sample cover photo, and content type (articles, product reviews).
MySQL JS > coll1.add({ name: 'Oracle Magazine', publisher: 'Oracle Publishing', frequencyPerYear: 6, category: 'Information Technology', mediaType: 'Print', since: '1980', contentType: 'articles,product reviews,industry spotlight', coverPhoto: "" }).execute();
Query OK, 1 item affected (0.1139 sec)
As the data model evolves new documents may be added with different sets of attributes.
Using the X DevAPI Collection Object
The X DevAPI Collection
Object provides functions to perform basic CRUD operations. These functions are:
Method | Description |
Collection.add() | Adds a document |
Collection.find)_ | Finds a document |
Collection.modify)_ | Modifies a document |
Collection.remove)_ | Removes a document |
We already showed examples of using Collection.add()
. As another example, find documents. The following JavaScript finds and lists all documents in the magazine_catalog collection.
MySQL JS > var coll1 = db.getCollection('magazine_catalog');
MySQL JS > coll1.find().execute();
{
"_id": "0000637ba38d0000000000000001",
"age": 19,
"name": "PHP Magazine"
}
{
"_id": "0000637ba38d0000000000000002",
"name": "Java Magazine",
"category": "Information Technology",
"mediaType": "Print",
"publisher": "Oracle Publishing",
"frequencyPerYear": 6
}
{
"_id": "0000637ba38d0000000000000003",
"name": "Oracle Magazine",
"since": "1980",
"category": "Information Technology",
"mediaType": "Print",
"publisher": "Oracle Publishing",
"coverPhoto": "",
"contentType": "articles,product reviews,industry spotlight",
"frequencyPerYear": 6
}
3 documents in set (0.0215 sec)
Exploring Data Model Options
After evaluating the data model development, you need to make some selections such as:
- Which data attributes should be included?
- Is a JSON document store a better alternative to a relational database table?
Selecting Data Attributes
Some data attributes are essential, such as magazine name, publisher, category, content type, publication frequency, and media type, while other data attributes may be considered as secondary, or optional; attributes such as sample cover photo, and published since.
Selecting a Data Model
Three data model options are available:
- Document Store Collection
- RDBMS table with a column for each attribute
- JSON type column
We have already explored the Collection option.
RDBMS Table
If you choose a RDBMS data model, your data definition DDL may be something like:
CREATE TABLE magazine_catalog1(name VARCHAR(255),publisher VARCHAR(255), category VARCHAR(255), content_type VARCHAR(255), publication_frequency INT,media_type VARCHAR(255));
Perhaps you find the RDBMS data model too rigid, or inflexible. Would a data modeler have a problem finding data for all data attributes for each of the magazines? You may want to consider a JSON data type based data model.
Using the JSON Data Type
The JSON data type is available since version 5.7. Its main benefits are:
- Adaptive/Flexible
- Schema-less
- Support for several JSON-related built-in functions
- Automatic validation of JSON data
- Optimized binary storage format
- Efficient read access
The following DDL creates a table with a JSON type column.
mysql> CREATE TABLE catalog(id INT, magazine JSON);
Query OK, 0 rows affected (0.23 sec)
Add three sample rows of data:
mysql> INSERT INTO catalog VALUES(1,'{"name": "PHP Magazine"}');
Query OK, 1 row affected (0.05 sec)
mysql>
mysql> INSERT INTO catalog VALUES(2,'{"name": "Java Magazine", "publisher": "Oracle Publishing", "frequencyPerYear": 6, "category": "Information Technology", "mediaType": "Print", "since": "1980"}');
Query OK, 1 row affected (0.02 sec)
mysql>
mysql> INSERT INTO catalog VALUES(3,'{"name": "Oracle Magazine", "publisher": "Oracle Publishing", "frequencyPerYear": 6, "category": "Information Technology", "mediaType": "Print", "since": "1980", "contentType": "articles,product reviews,industry spotlight", "coverPhoto": "" }');
Query OK, 1 row affected (0.02 sec)
Select data added:
mysql> SELECT * from catalog
-> ;
+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | magazine |
+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 1 | {"name": "PHP Magazine"} |
| 2 | {"name": "Java Magazine", "since": "1980", "category": "Information Technology", "mediaType": "Print", "publisher": "Oracle Publishing", "frequencyPerYear": 6} |
| 3 | {"name": "Oracle Magazine", "since": "1980", "category": "Information Technology", "mediaType": "Print", "publisher": "Oracle Publishing", "coverPhoto": "", "contentType": "articles,product reviews,industry spotlight", "frequencyPerYear": 6} |
+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
3 rows in set (0.00 sec)
Using the JSON Functions
MySQL provides several built-in functions that could be used with JSON. The functions may be categorized by their use as follows:
Function Category | Some Functions in Category |
Create JSON Values | JSON_OBJECT(), JSON_ARRAY() |
Search JSON Values | JSON_SEARCH(), JSON_EXTRACT() |
Modify JSON Values | JSON_APPEND(), JSON_INSERT(),JSON_MERGE(), JSON_REMOVE() |
Return JSON Value Attributes | JSON_VALUE(), JSON_LENGTH(),JSON_TYPE(), JSON_VALID() |
As an example, validate JSON in the catalog table.
mysql> SELECT JSON_VALID(magazine) FROM catalog;
+----------------------+
| JSON_VALID(magazine) |
+----------------------+
| 1 |
| 1 |
| 1 |
+----------------------+
3 rows in set (0.03 sec)
Using the X DevAPI Table Object
The X DevAPI Table object provides SQL CRUD functions for relational tables. These are:
X DevAPI | Description |
Table.insert() | Adds data to a relational table |
Table.select() | Selects data from a relational table |
Table.update() | Updates data in a relational table |
Table.delete() | Deletes a relational table data |
As an example, select data from the catalog table.
MySQL JS >var mysqlx = require('mysqlx');
Create a Server Session.
MySQL JS >var s1 = mysqlx.getSession( {
host: 'localhost', port: 33060,
user: 'root', password: 'mysql'} );
Get a Database object.
MySQL JS >var db = s1.getSchema('world');
Access an existing table.
MySQL JS >var table1 = db.getTable('catalog');
Find a row in the SQL Table.
MySQL JS >var result = table1.select(['id', 'magazine']).execute();
Print result.
MySQL JS >print(result.fetchOne());
The result is:
[
1,
"{\"name\": \"PHP Magazine\"}"
]