MySQL JSON Document Store
Introduction
MySQL is the most popular Open Source database!
An ACID (acronym standing for Atomicity, Consistency, Isolation, and Durability) compliant relational database that allows you, among others, to manage your data with the powerful and proven SQL, to take care of your data integrity with transactions, foreign keys, …
But you already know that 🙂
JavaScript Objet Notation, better known as JSON, is a lightweight and very popular data-interchange format. Use for storing and exchanging data.
A JSON document is a standardized object that can represent structured data. And the structure is implicit in the document.
Anyway, I bet you know that too!
Started with MySQL 5.7.8, you can handle JSON documents in a “relational way”, using SQL queries and also storing them using the MySQL native JSON data type.
We also provides a large set of JSON functions.
I hope you were aware of that!
You should be interested in:
Note:
I would recommend you to have a closer look at JSON_TABLE function, that extract data from a JSON document and returns it as a relational table… It’s just amazing!
However MySQL 8.0 provides another way to handle JSON documents, actually in a “Not only SQL” (NoSQL) approach…
In other words, if you need/want to manage JSON documents (collections) in a non-relational manner, with CRUD (acronym for Create/Read/Update/Delete) operations then you can use MySQL 8.0!
Did you know that?
MySQL Document Store Architecture
Let’s have a quick overview of the architecture.
- X Plugin – The X Plugin enables MySQL to use the X Protocol and uses Connectors and the Shell to act as clients to the server.
- X Protocol – The X Protocol is a new client protocol based on top of the Protobuf library, and works for both, CRUD and SQL operations.
- X DevAPI – The X DevAPI is a new, modern, async developer API for CRUD and SQL operations on top of X Protocol. It introduces Collections as new Schema objects. Documents are stored in Collections and have their dedicated CRUD operation set.
- MySQL Shell – The MySQL Shell is an interactive Javascript, Python, or SQL interface supporting development and administration for the MySQL Server. You can use the MySQL Shell to perform data queries and updates as well as various administration operations.
- MySQL Connectors – Connectors that support the X Protocol and enable you to use X DevAPI in your chosen language (Node.js – PHP – Python – Java – .NET – C++,…).
Write application using X DevAPI
As a disclaimer, I am not a developer, so sorry no fancy code in this blog post.
However the good news is that I can show you were you’ll be able to found the best MySQL developer resources ever 🙂 that is :
And to start, I recommend to focus on the following articles:
- Node.JS
- Python
- .NET
- Java
- PHP
- C++
- ODBC
And of course the newest articles as well.
Furthermore, another resource that would be useful to you is the
Use Document Store with MySQL Shell
If you are a DBA, OPS and obviously a developer, the simplest way to use (or test) MySQL Document Store, is with MySQL Shell.
MySQL Shell is an integrated development & administration shell where all MySQL products will be available through a common scripting interface.
If you don’t know it yet, please download it.
Trust me you are going to love it !
MySQL Shell key features are :
- Scripting for Javascript, Python, and SQL mode
- Supports MySQL Standard and X Protocols
- Document and Relational Models
- CRUD Document and Relational APIs via scripting
- Traditional Table, JSON, Tab Separated output results formats
- Both Interactive and Batch operations
Note:
MySQL Shell is also a key component of MySQL InnoDB Cluster. In this context, it allows you to deploy and manager a MySQL Group Replication cluster.
See my MySQL InnoDB Cluster tutorial.
First steps with MySQL Shell
Let’s connect to the MySQL Server with MySQL Shell (mysqlsh)
$ mysqlsh root@myHost
MySQL Shell 8.0.15
... snip ...
Your MySQL connection id is 15 (X protocol)
Server version: 8.0.15 MySQL Community Server - GPL
No default schema selected; type \use <schema> to set one.
We must be inside a X session in order to use MySQL as a document store. Luckily there is no extra step, because it’s the default in MySQL 8.0. Note that the default “X” port is 33060.
You can check that you are inside a X session thus using X protocol
MySQL myHost:33060+ JS> session
<Session:root@myHost:33060>
MySQL myHost:33060+ JS> \status
...snip...
Session type: X
Default schema:
Current schema:
Server version: 8.0.15 MySQL Community Server - GPL
Protocol version: X protocol
...snip...
If you are connected inside a classic session, you’ll get the following input (note “<ClassicSession instead of <Session”) :
MySQL myHost:3306 JS> session
<ClassicSession:root@myHost:3306>
You can know what is you X protocol port by checking mysqlx_port variable.
I’ll switch to the MySQL Shell SQL mode to execute my SQL command:
MySQL myHost:3306 JS> \sql
Switching to SQL mode... Commands end with ;
MySQL myHost:3306 SQL> SHOW VARIABLES LIKE 'mysqlx_port';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| mysqlx_port | 33060 |
+---------------+-------+
Then reconnect to the server using the right port (33060 by default) and you should be fine :
MySQL myHost:3306 SQL> \connect root@myHost:33060
...snip...
Your MySQL connection id is 66 (X protocol)
Server version: 8.0.15 MySQL Community Server - GPL
No default schema selected; type \use <schema> to set one.
MySQL myHost:33060+ SQL> \js
Switching to JavaScript mode...
MySQL myHost:33060+ JS> session
<Session:root@myHost:33060>
CRUD
We are going to create a schema (demo) where we will do our tests
MySQL myHost:33060+ JS> session.createSchema('demo')
<Schema:demo>
MySQL myHost:33060+ JS> \use demo
Default schema `demo` accessible through db.
Note:
The MySQL Shell default language is JavaScript. However, all the steps described in this article can also be done in Python.
e.g.
JS> session.createSchema(‘demo’)
Py> session.create_schema(‘demo’)
Create documents
Create a collection (my_coll1) insert the schema demo and insert documents :
MySQL myHost:33060+ demo JS> db.createCollection('my_coll1');
<Collection:my_coll1>
MySQL myHost:33060+ demo JS> db.my_coll1.add({"title":"MySQL Document Store", "abstract":"SQL is now optional!", "code": "42"})
Query OK, 1 item affected (0.0358 sec)
Trying to add a non valid JSON document raise an error :
MySQL myHost:33060+ demo JS> db.my_coll1.add("This is not a valid JSON document")
CollectionAdd.add: Argument #1 expected to be a document, JSON expression or a list of documents (ArgumentError)
List collections
To get the list of collections belonging to the current schema use getCollections() :
MySQL myHost:33060+ demo JS> db.getCollections()
[
<Collection:my_coll1>
]
Find documents
Display the content of a collection with find() :
MySQL myHost:33060+ demo JS> db.my_coll1.find()
[
{
"_id": "00005c9514e60000000000000053",
"code": "42",
"title": "MySQL Document Store",
"abstract": "SQL is now optional!"
}
]
1 document in set (0.0029 sec)
Note:
Each document requires an identifier field called _id. The value of the _id field must be unique among all documents in the same collection.
MySQL server sets an _id value if the document does not contain the _id field.Please read: Understanding Document IDs.
You can execute many operations on your document. One practical way to get the list of available functions is to press the <TAB> key, to ask for auto-completion, after the dot “.”
For example, type db.my_coll1. then press <TAB>twice, you’ll get the following result:
MySQL myHost:33060+ demo JS> db.my_coll1.
add() count() dropIndex() find() getOne() getSession() modify() remove() replaceOne() session
addOrReplaceOne() createIndex() existsInDatabase() getName() getSchema() help() name removeOne() schema
You can also use the awesome MySQL Shell built-in help (I strongly recommend my colleague Jesper‘s article) and please bookmark is blog.
Last but not least our documentations: X DevAPI User Guide, MySQL Shell JavaSCript API Reference & MySQL Shell Python API reference.
Modify documents
You’ll need the modify() function :
MySQL myHost:33060+ demo JS> db.my_coll1.find("_id='00005c9514e60000000000000053'").fields("code")
[
{
"code": "42"
}
]
MySQL myHost:33060+ demo JS> db.my_coll1.modify("_id='00005c9514e60000000000000053'").set("code","2019")
Query OK, 1 item affected (0.0336 sec)
Rows matched: 1 Changed: 1 Warnings: 0
MySQL myHost:33060+ demo JS> db.my_coll1.find("_id='00005c9514e60000000000000053'").fields("code")
[
{
"code": "2019"
}
]
Remove content from documents
You can also modify the structure of a document by remove a key and its content with modify() and unset().
MySQL myHost:33060+ demo JS> db.my_coll1.add({"title":"Quote", "message": "Strive for greatness"})
Query OK, 1 item affected (0.0248 sec)
MySQL myHost:33060+ demo JS> db.my_coll1.find()
[
{
"_id": "00005c9514e60000000000000053",
"code": "42",
"title": "MySQL Document Store",
"abstract": "SQL is now optional!"
},
{
"_id": "00005c9514e60000000000000054",
"title": "Quote",
"message": "Strive for greatness"
}
]
2 documents in set (0.0033 sec)
MySQL myHost:33060+ demo JS> db.my_coll1.modify("_id='00005c9514e60000000000000054'").unset("title")
Query OK, 1 item affected (0.0203 sec)
Rows matched: 1 Changed: 1 Warnings: 0
MySQL myHost:33060+ demo JS> db.my_coll1.find("_id='00005c9514e60000000000000054'")
[
{
"_id": "00005c9514e60000000000000054",
"message": "Strive for greatness"
}
]
Remove documents
We are missing one last important operation, delete documents with remove()
MySQL myHost:33060+ demo JS> db.my_coll1.remove("_id='00005c9514e60000000000000054'")
Query OK, 1 item affected (0.0625 sec)
MySQL myHost:33060+ demo JS> db.my_coll1.find("_id='00005c9514e60000000000000054'")
Empty set (0.0003 sec)
You can also remove all documents in a collection with one command. To do so, use the remove(“true”) method without specifying any search condition.
Obviously it is usually not a good practice…
Import JSON dcouments
Let’s work with a bigger JSON collection.
MySQL Shell provide a very convenient tool, named importJson(), to easily import JSON documents inside your MySQL Server either in the form of collection or table.
MySQL myHost:33060+ demo JS> db.getCollections()
[
<Collection:my_coll1>
]
MySQL myHost:33060+ demo JS> util.importJson('GoT_episodes.json')
Importing from file "GoT_episodes.json" to collection `demo`.`GoT_episodes` in MySQL Server at myHost:33060
.. 73.. 73
Processed 47.74 KB in 73 documents in 0.1051 sec (694.75 documents/s)
Total successfully imported documents 73 (694.75 documents/s)
MySQL myHost:33060+ demo JS> db.getCollections()
[
<Collection:GoT_episodes>,
<Collection:my_coll1>
]
You can find the JSON file source here.
Note that I had to do an extra step before import the data:
sed ‘s/}}},{“id”/}}} {“id”/g’ got_episodes.json.BAK > got_episodes.json
By the way you can import data from MongoDB to MySQL \o/
- Importing Data from MongoDB to MySQL: BSON Data Types
- Importing Data from MongoDB to MySQL using JavaScript
- Importing Data from MongoDB to MySQL using Python
- Conversions for representations of BSON data types
No more excuses to finally get rid of MongoDB 😉
Let’s do some queries…
Display 1 document
MySQL myHost:33060+ demo JS> db.GoT_episodes.find().limit(1)
[
{
"id": 4952,
"_id": "00005c9514e6000000000000009e",
"url": "http://www.tvmaze.com/episodes/4952/game-of-thrones-1x01-winter-is-coming",
"name": "Winter is Coming",
"image": {
"medium": "http://static.tvmaze.com/uploads/images/medium_landscape/1/2668.jpg",
"original": "http://static.tvmaze.com/uploads/images/original_untouched/1/2668.jpg"
},
"_links": {
"self": {
"href": "http://api.tvmaze.com/episodes/4952"
}
},
"number": 1,
"season": 1,
"airdate": "2011-04-17",
"airtime": "21:00",
"runtime": 60,
"summary": "<p>Lord Eddard Stark, ruler of the North, is summoned to court by his old friend, King Robert Baratheon, to serve as the King's Hand. Eddard reluctantly agrees after learning of a possible threat to the King's life. Eddard's bastard son Jon Snow must make a painful decision about his own future, while in the distant east Viserys Targaryen plots to reclaim his father's throne, usurped by Robert, by selling his sister in marriage.</p>",
"airstamp": "2011-04-18T01:00:00+00:00"
}
]
Looks like data relative to a famous TV show 🙂
All episodes from season 1
MySQL myHost:33060+ demo JS> db.GoT_episodes.find("season=1").fields("name", "summary", "airdate").sort("number")
[
{
"name": "Winter is Coming",
"airdate": "2011-04-17",
"summary": "<p>Lord Eddard Stark, ruler of the North, is summoned to court by his old friend, King Robert Baratheon, to serve as the King's Hand. Eddard reluctantly agrees after learning of a possible threat to the King's life. Eddard's bastard son Jon Snow must make a painful decision about his own future, while in the distant east Viserys Targaryen plots to reclaim his father's throne, usurped by Robert, by selling his sister in marriage.</p>"
},
{
"name": "The Kingsroad",
"airdate": "2011-04-24",
"summary": "<p>An incident on the Kingsroad threatens Eddard and Robert's friendship. Jon and Tyrion travel to the Wall, where they discover that the reality of the Night's Watch may not match the heroic image of it.</p>"
},
{
"name": "Lord Snow",
"airdate": "2011-05-01",
"summary": "<p>Jon Snow attempts to find his place amongst the Night's Watch. Eddard and his daughters arrive at King's Landing.</p>"
},
{
"name": "Cripples, Bastards, and Broken Things",
"airdate": "2011-05-08",
"summary": "<p>Tyrion stops at Winterfell on his way home and gets a frosty reception from Robb Stark. Eddard's investigation into the death of his predecessor gets underway.</p>"
},
{
"name": "The Wolf and the Lion",
"airdate": "2011-05-15",
"summary": "<p>Catelyn's actions on the road have repercussions for Eddard. Tyrion enjoys the dubious hospitality of the Eyrie.</p>"
},
{
"name": "A Golden Crown",
"airdate": "2011-05-22",
"summary": "<p>Viserys is increasingly frustrated by the lack of progress towards gaining his crown.</p>"
},
{
"name": "You Win or You Die",
"airdate": "2011-05-29",
"summary": "<p>Eddard's investigations in King's Landing reach a climax and a dark secret is revealed.</p>"
},
{
"name": "The Pointy End",
"airdate": "2011-06-05",
"summary": "<p>Tyrion joins his father's army with unexpected allies. Events in King's Landing take a turn for the worse as Arya's lessons are put to the test.</p>"
},
{
"name": "Baelor",
"airdate": "2011-06-12",
"summary": "<p>Catelyn must negotiate with the irascible Lord Walder Frey.</p>"
},
{
"name": "Fire and Blood",
"airdate": "2011-06-19",
"summary": "<p>Daenerys must realize her destiny. Jaime finds himself in an unfamiliar predicament.</p>"
}
]
First episode of each season
MySQL myHost:33060+ demo JS> db.GoT_episodes.find("number=1").fields("name", "airdate", "season").sort("season")
[
{
"name": "Winter is Coming",
"season": 1,
"airdate": "2011-04-17"
},
{
"name": "The North Remembers",
"season": 2,
"airdate": "2012-04-01"
},
{
"name": "Valar Dohaeris",
"season": 3,
"airdate": "2013-03-31"
},
{
"name": "Two Swords",
"season": 4,
"airdate": "2014-04-06"
},
{
"name": "The Wars to Come",
"season": 5,
"airdate": "2015-04-12"
},
{
"name": "The Red Woman",
"season": 6,
"airdate": "2016-04-24"
},
{
"name": "Dragonstone",
"season": 7,
"airdate": "2017-07-16"
},
{
"name": "TBA",
"season": 8,
"airdate": "2019-04-14"
}
]
8 documents in set (0.0047 sec)
CRUD Prepared Statements
A common pattern with document store datastores is to repeatedly execute the same (or similar) kind of simple queries (e.g. “id” based lookup).
These queries can be accelerated using prepared (CRUD) statements.
For example if your application often use the following query:
MySQL myHost:33060+ demo JS> db.GoT_episodes.find("number=1 AND season=1").fields("name", "airdate")
[
{
"name": "Winter is Coming",
"airdate": "2011-04-17"
}
]
So it’s probably a good idea to use prepared statements.
First we need to prepare the query:
// Prepare a statement using a named parameter
var gotEpisode = db.GoT_episodes.find("number = :episodeNum AND season = :seasonNum").fields("name", "airdate")
Then bind the value to the parameter :
MySQL myHost:33060+ demo JS> gotEpisode.bind('episodeNum', 1).bind('seasonNum', 1)
[
{
"name": "Winter is Coming",
"airdate": "2011-04-17"
}
]
MySQL myHost:33060+ demo JS> gotEpisode.bind('episodeNum', 7).bind('seasonNum', 3)
[
{
"name": "The Bear and the Maiden Fair",
"airdate": "2013-05-12"
}
]
Simply powerful!
Index
Indeed relevant indexes is a common practice to improve performances. MySQL Document Store allows you to index your keys inside the JSON document.
Add a composite Index on keys season AND episode.
MySQL myHost:33060+ demo JS> db.GoT_episodes.createIndex('idxSeasonEpisode', {fields: [{field: "$.season", type: "TINYINT UNSIGNED", required: true}, {field: "$.number", type: "TINYINT UNSIGNED", required: true}]})
Query OK, 0 rows affected (0.1245 sec)
The required: true option means that it’s mandatory for all documents to contains at least the keys number and season.
E.g.
MySQL myHost:33060+ demo JS> db.GoT_episodes.add({"name": "MySQL 8 is Great"})
ERROR: 5115: Document is missing a required field
MySQL myHost:33060+ demo JS> db.GoT_episodes.add({"name": "MySQL 8 is Great", "number": 8})
ERROR: 5115: Document is missing a required field
MySQL myHost:33060+ demo JS> db.GoT_episodes.add({"name": "MySQL 8 is Great", "season": 8})
ERROR: 5115: Document is missing a required field
Add an index on key summary (30 first characters)
MySQL myHost:33060+ demo JS> db.GoT_episodes.createIndex('idxSummary', {fields: [{field: "$.summary", type: "TEXT(30)"}]})
Query OK, 0 rows affected (0.1020 sec)
Add a Unique Index on key id
Not the one generated by MySQL called _id and already indexed (primary key)
MySQL myHost:33060+ demo JS> db.GoT_episodes.createIndex('idxId', {fields: [{field: "$.id", type: "INT UNSIGNED"}], unique: true})
Query OK, 0 rows affected (0.3379 sec)
The unique: true option means that values of key id must be unique for each document inside the collection. i.e. no duplicate values.
E.g.
MySQL myHost:33060+ demo JS> db.GoT_episodes.add({"id":4952, "number": 42, "season": 42 })
ERROR: 5116: Document contains a field value that is not unique but required to be
You can obviously drop an index, using dropIndex().
E.g. db.GoT_episodes.dropIndex(“idxSummary”)
Transactions
MySQL Document Store is full ACID, it relies on the proven InnoDB’s strength & robustness.
Yes, you get it right, We do care about your data!
You need the functions below:
Let’s see an example with a multi collection transactions that will be rollback.
// Start the transaction
session.startTransaction()
MySQL myHost:33060+ demo JS> db.my_coll1.find()
[
{
"_id": "00005c9514e60000000000000053",
"code": "42",
"title": "MySQL Document Store",
"abstract": "SQL is now optional!"
}
]
1 document in set (0.0033 sec)
// Modify a document in collection my_coll1
MySQL myHost:33060+ demo JS> db.my_coll1.modify("_id = '00005c9514e60000000000000053'").unset("code")
Query OK, 1 item affected (0.0043 sec)
Rows matched: 1 Changed: 1 Warnings: 0
//Collection 1 : my_coll1
// Add a new document in my_coll1
MySQL myHost:33060+ demo JS> db.my_coll1.add({"title":"Quote", "message": "Be happy, be bright, be you"})
Query OK, 1 item affected (0.0057 sec)
MySQL myHost:33060+ demo JS> db.my_coll1.find()
[
{
"_id": "00005c9514e60000000000000053",
"title": "MySQL Document Store",
"abstract": "SQL is now optional!"
},
{
"_id": "00005c9514e600000000000000e7",
"title": "Quote",
"message": "Be happy, be bright, be you"
}
]
2 documents in set (0.0030 sec)
// Collection 2 : GoT_episodes
// Number of documents in GoT_episodes
MySQL myHost:33060+ demo JS> db.GoT_episodes.count()
73
// Remove all the 73 documents from GoT_episodes
MySQL myHost:33060+ demo JS> db.GoT_episodes.remove("true")
Query OK, 73 items affected (0.2075 sec)
// Empty collection
MySQL myHost:33060+ demo JS> db.GoT_episodes.count()
0
// Finally want my previous status back
// Rollback the transaction (if necessary e.g. in case of an error)
MySQL myHost:33060+ demo JS> session.rollback()
Query OK, 0 rows affected (0.0174 sec)
Tadam!!!
We back in the past 🙂
MySQL myHost:33060+ demo JS> db.my_coll1.find()
[
{
"_id": "00005c9514e60000000000000053",
"code": "42",
"title": "MySQL Document Store",
"abstract": "SQL is now optional!"
}
]
1 document in set (0.0028 sec)
MySQL myHost:33060+ demo JS> db.GoT_episodes.count()
73
Execute (complex) SQL queries
From the MySQL server point of view, collections are tables as well, like regular tables.
And this is very powerful !!!
Powerful because that allow you, within the same datastore (MySQL), to do CRUD queries and SQL queries on the same dataset.
Powerful because that allow you, to have your OLTP CRUD workload and your analytics SQL workload at the same place.
So no need to transfer/sync/… data from 1 datastore to another anymore!!!
You can do SQL queries using sql() functions:
MySQL myHost:33060+ demo JS> session.sql("SELECT count(*) FROM GoT_episodes")
+----------+
| count(*) |
+----------+
| 73 |
+----------+
You can also do SQL queries just as you have done until now, using the rich set of MySQL JSON functions.
OK let’s have a closer look.
Remember this CRUD query?
MySQL myHost:33060+ demo JS> db.GoT_episodes.find("number=1 AND season=1").fields("name", "airdate")
[
{
"name": "Winter is Coming",
"airdate": "2011-04-17"
}
]
Its SQL query alter ego is :
MySQL myHost:33060+ demo JS> \sql
MySQL myHost:33060+ demo SQL>
SELECT doc->>"$.name" AS name, doc->>"$.airdate" AS airdate
FROM GoT_episodes
WHERE doc->>"$.number" = 1 AND doc->>"$.season" = 1\G
*************************** 1. row ***************************
name: Winter is Coming
airdate: 2011-04-17
Let’s do some SQL queries…
Number of episodes by season
MySQL myHost:33060+ demo SQL>
SELECT doc->>"$.season", COUNT(doc->>"$.number")
FROM GoT_episodes
GROUP BY doc->>"$.season";
+------------------+-------------------------+
| doc->>"$.season" | count(doc->>"$.number") |
+------------------+-------------------------+
| 1 | 10 |
| 2 | 10 |
| 3 | 10 |
| 4 | 10 |
| 5 | 10 |
| 6 | 10 |
| 7 | 7 |
| 8 | 6 |
+------------------+-------------------------+
Episode statistics for each season
MySQL myHost:33060+ demo SQL>
SELECT DISTINCT
doc->>"$.season" AS Season,
max(doc->>"$.runtime") OVER w AS "Max duration",
min(doc->>"$.runtime") OVER w AS "Min duration",
AVG(doc->>"$.runtime") OVER w AS "Avg duration"
FROM GoT_episodes
WINDOW w AS (
PARTITION BY doc->>"$.season"
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
);
+--------+--------------+--------------+--------------+
| Season | Max duration | Min duration | Avg duration |
+--------+--------------+--------------+--------------+
| 1 | 60 | 60 | 60 |
| 2 | 60 | 60 | 60 |
| 3 | 60 | 60 | 60 |
| 4 | 60 | 60 | 60 |
| 5 | 60 | 60 | 60 |
| 6 | 69 | 60 | 60.9 |
| 7 | 60 | 60 | 60 |
| 8 | 90 | 60 | 80 |
+--------+--------------+--------------+--------------+
Statistics on the number of days between episodes
MySQL myHost:33060+ demo SQL>
SELECT
doc->>"$.airdate" AS airdate,
DATEDIFF(doc->>"$.airdate", lag(doc->>"$.airdate") OVER w) AS "Delta days between episode",
DATEDIFF(doc->>"$.airdate", first_value(doc->>"$.airdate") OVER w) AS "Total days since 1st episode"
FROM GoT_episodes
WINDOW w AS (ORDER BY doc->>"$.airdate")
;
+------------+----------------------------+------------------------------+
| airdate | Delta days between episode | Total days since 1st episode |
+------------+----------------------------+------------------------------+
| 2011-04-17 | NULL | 0 |
| 2011-04-24 | 7 | 7 |
| 2011-05-01 | 7 | 14 |
| 2011-05-08 | 7 | 21 |
| 2011-05-15 | 7 | 28 |
| 2011-05-22 | 7 | 35 |
| 2011-05-29 | 7 | 42 |
| 2011-06-05 | 7 | 49 |
| 2011-06-12 | 7 | 56 |
| 2011-06-19 | 7 | 63 |
| 2012-04-01 | 287 | 350 |
| 2012-04-08 | 7 | 357 |
| 2012-04-15 | 7 | 364 |
| 2012-04-22 | 7 | 371 |
| 2012-04-29 | 7 | 378 |
| 2012-05-06 | 7 | 385 |
| 2012-05-13 | 7 | 392 |
| 2012-05-20 | 7 | 399 |
| 2012-05-27 | 7 | 406 |
| 2012-06-03 | 7 | 413 |
| 2013-03-31 | 301 | 714 |
| 2013-04-07 | 7 | 721 |
| 2013-04-14 | 7 | 728 |
| 2013-04-21 | 7 | 735 |
| 2013-04-28 | 7 | 742 |
| 2013-05-05 | 7 | 749 |
| 2013-05-12 | 7 | 756 |
| 2013-05-19 | 7 | 763 |
| 2013-06-02 | 14 | 777 |
| 2013-06-09 | 7 | 784 |
| 2014-04-06 | 301 | 1085 |
| 2014-04-13 | 7 | 1092 |
| 2014-04-20 | 7 | 1099 |
| 2014-04-27 | 7 | 1106 |
| 2014-05-04 | 7 | 1113 |
| 2014-05-11 | 7 | 1120 |
| 2014-05-18 | 7 | 1127 |
| 2014-06-01 | 14 | 1141 |
| 2014-06-08 | 7 | 1148 |
| 2014-06-15 | 7 | 1155 |
| 2015-04-12 | 301 | 1456 |
| 2015-04-19 | 7 | 1463 |
| 2015-04-26 | 7 | 1470 |
| 2015-05-03 | 7 | 1477 |
| 2015-05-10 | 7 | 1484 |
| 2015-05-17 | 7 | 1491 |
| 2015-05-24 | 7 | 1498 |
| 2015-05-31 | 7 | 1505 |
| 2015-06-07 | 7 | 1512 |
| 2015-06-14 | 7 | 1519 |
| 2016-04-24 | 315 | 1834 |
| 2016-05-01 | 7 | 1841 |
| 2016-05-08 | 7 | 1848 |
| 2016-05-15 | 7 | 1855 |
| 2016-05-22 | 7 | 1862 |
| 2016-05-29 | 7 | 1869 |
| 2016-06-05 | 7 | 1876 |
| 2016-06-12 | 7 | 1883 |
| 2016-06-19 | 7 | 1890 |
| 2016-06-26 | 7 | 1897 |
| 2017-07-16 | 385 | 2282 |
| 2017-07-23 | 7 | 2289 |
| 2017-07-30 | 7 | 2296 |
| 2017-08-06 | 7 | 2303 |
| 2017-08-13 | 7 | 2310 |
| 2017-08-20 | 7 | 2317 |
| 2017-08-27 | 7 | 2324 |
| 2019-04-14 | 595 | 2919 |
| 2019-04-21 | 7 | 2926 |
| 2019-04-28 | 7 | 2933 |
| 2019-05-05 | 7 | 2940 |
| 2019-05-12 | 7 | 2947 |
| 2019-05-19 | 7 | 2954 |
+------------+----------------------------+------------------------------+
73 rows in set (0.0066 sec)
Note:
Hey buddy, aren’t Window Functions very cool?
Drop collections
Use dropCollection() :
MySQL myHost:33060+ demo JS> db.getCollections()
[
<Collection:GoT_episodes>,
<Collection:my_coll1>
]
MySQL myHost:33060+ demo JS> db.dropCollection("my_coll1")
MySQL myHost:33060+ demo JS> db.getCollections()
[
<Collection:GoT_episodes>
]
Conclusion
Wow!
Probably one of my longest article, but I wanted to be sure to give you a large overview of MySQL Document Store (although not exhaustive) from a point of view of a non developer.
Now it is your turn to give it a try 🙂
NoSQL + SQL = MySQL
In order to go further
Some useful link:
- Top 10 reasons for NoSQL with MySQL
- MySQL Document Store Overview
- Moving to the Future from MongoDB to MySQL Document Store
- Using MySQL as a Document Store
- MySQL Engineering Blog
- X DevAPI User Guide
- MySQL Shell JavaSCript API Reference
- MySQL Shell Python API reference
- X plugin
- X protocol
- MySQL Shell
Thanks for using MySQL!
Watch my videos on my YouTube channel and subscribe.
Thanks for using HeatWave & MySQL!
Cloud Solutions Architect at Oracle
MySQL Geek, author, blogger and speaker
I’m an insatiable hunger of learning.
—–
Blog: www.dasini.net/blog/en/
Twitter: https://twitter.com/freshdaz
SlideShare: www.slideshare.net/freshdaz
Youtube: https://www.youtube.com/channel/UC12TulyJsJZHoCmby3Nm3WQ
—–
[…] Note 3: Handling JSON documents could be also done with MySQL Document Store. […]
[…] Note 2: Handling JSON documents could be also done with MySQL Document Store. […]
[…] Note 3: Tu peux également manipuler tes documents JSON avec MySQL Document Store. […]
[…] Note 2: Tu peux également manipuler tes documents JSON avec MySQL Document Store. […]
[…] MySQL JSON Document Store […]
[…] mais sobre – clicando nesse link! Exemplos e […]
thanks for yor sharing