
{"id":2874,"date":"2019-04-02T10:00:17","date_gmt":"2019-04-02T09:00:17","guid":{"rendered":"http:\/\/dasini.net\/blog\/?p=2874"},"modified":"2019-04-03T14:29:06","modified_gmt":"2019-04-03T13:29:06","slug":"mysql-json-document-store","status":"publish","type":"post","link":"https:\/\/dasini.net\/blog\/2019\/04\/02\/mysql-json-document-store\/","title":{"rendered":"MySQL JSON Document Store"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>MySQL is the most popular Open Source database! <br>An <a rel=\"noreferrer noopener\" aria-label=\"ACID (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/glossary.html#glos_acid\" target=\"_blank\">ACID<\/a> (acronym standing for <strong>A<\/strong>tomicity, <strong>C<\/strong>onsistency, <strong>I<\/strong>solation, and <strong>D<\/strong>urability) compliant relational database that allows you, among others, to manage your data with the powerful and proven <a rel=\"noreferrer noopener\" aria-label=\"SQL (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/glossary.html#glos_sql\" target=\"_blank\">SQL<\/a>, to take care of  your data integrity with <a rel=\"noreferrer noopener\" aria-label=\"transactions (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/glossary.html#glos_transaction\" target=\"_blank\">transactions<\/a>, <a rel=\"noreferrer noopener\" aria-label=\"foreign keys (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/glossary.html#glos_foreign_key\" target=\"_blank\">foreign keys<\/a>, &#8230; <br><em>But you already know that \ud83d\ude42<\/em><\/p>\n\n\n\n<p><strong>J<\/strong>ava<strong>S<\/strong>cript <strong>O<\/strong>bjet <strong>N<\/strong>otation, better known as <a rel=\"noreferrer noopener\" aria-label=\"JSON (opens in a new tab)\" href=\"https:\/\/www.json.org\/\" target=\"_blank\">JSON<\/a>, is a lightweight and very popular data-interchange format. Use for storing and exchanging data.<br>A JSON document is a standardized object that can represent structured data. And the structure is implicit in the document.<br><em>Anyway, I bet you know that too!<\/em><\/p>\n\n\n\n<p>Started with MySQL 5.7.8, you can <strong>handle JSON documents<\/strong> in a \u00ab\u00a0relational way\u00a0\u00bb, using SQL queries and also storing them using the MySQL native <a rel=\"noreferrer noopener\" aria-label=\"JSON data type (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/json.html\" target=\"_blank\">JSON data type<\/a>.<br>We also provides a large set of <a rel=\"noreferrer noopener\" aria-label=\"JSON functions (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/json-functions.html\" target=\"_blank\">JSON functions<\/a>. <br><em>I hope you were aware of that!<\/em><\/p>\n\n\n\n<p>You should be interested in:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a rel=\"noreferrer noopener\" aria-label=\"30 mins with MySQL JSON functions (opens in a new tab)\" href=\"http:\/\/dasini.net\/blog\/2018\/07\/23\/30-mins-with-mysql-json-functions\/\" target=\"_blank\">30 mins with MySQL JSON functions<\/a> <\/li><li><a href=\"http:\/\/dasini.net\/blog\/2015\/11\/17\/30-mins-with-json-in-mysql\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"30 mins with JSON in MySQL (opens in a new tab)\">30 mins with JSON in MySQL<\/a> <\/li><\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p><u>Note<\/u>:<\/p><p>I would recommend you to have a closer look at <a href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/json-table-functions.html\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"JSON_TABLE (opens in a new tab)\">JSON_TABLE<\/a> function, that extract data from a JSON document and returns it as a relational table&#8230; It&rsquo;s just amazing!<\/p><\/blockquote>\n\n\n\n<p>However MySQL 8.0 provides another way to handle JSON documents,  actually in a \u00ab\u00a0<strong>Not only SQL<\/strong>\u00a0\u00bb (<a rel=\"noreferrer noopener\" aria-label=\"NoSQL (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/glossary.html#glos_nosql\" target=\"_blank\">NoSQL<\/a>) approach&#8230; <br>In other words, if you need\/want to manage JSON documents (collections) in a non-relational manner, with <a rel=\"noreferrer noopener\" aria-label=\"CRUD (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/glossary.html#glos_crud\" target=\"_blank\">CRUD<\/a> (acronym for <strong>C<\/strong>reate\/<strong>R<\/strong>ead\/<strong>U<\/strong>pdate\/<strong>D<\/strong>elete) operations then you can use MySQL 8.0!<br><em>Did you know that?<\/em><\/p>\n\n\n\n\n\n<h2 class=\"wp-block-heading\">MySQL Document Store Architecture<\/h2>\n\n\n\n<p>Let&rsquo;s have a quick overview of the architecture.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/dasini.net\/blog\/wp-content\/uploads\/MySQL_8.0_Document_Store_Architecture.png\" alt=\"MySQL Document Store Architecture\"><figcaption><br><\/figcaption><\/figure><\/div>\n\n\n\n<ul class=\"wp-block-list\"><li><strong><a rel=\"noreferrer noopener\" aria-label=\"X Plugin (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/x-plugin.html\" target=\"_blank\">X Plugin<\/a><\/strong> &#8211; The X Plugin enables MySQL to use the X Protocol and uses Connectors and the Shell to act as clients to the server.<\/li><li><strong><a rel=\"noreferrer noopener\" aria-label=\"X Protocol (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/internals\/en\/x-protocol.html\" target=\"_blank\">X Protocol<\/a><\/strong> &#8211; The X Protocol is a new client protocol based on top of the Protobuf library, and works for both, <strong>CRUD and SQL<\/strong> operations.<\/li><li><strong><a rel=\"noreferrer noopener\" aria-label=\"X DevAPI (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/x-devapi-userguide\/en\/\" target=\"_blank\">X DevAPI<\/a><\/strong> &#8211; The X DevAPI is a new, modern, <strong>async developer API<\/strong> for CRUD and SQL operations on top of X Protocol. It introduces <strong>Collections<\/strong> as new Schema objects. Documents are stored in Collections and have their dedicated <strong>CRUD operation<\/strong> set.<\/li><li><strong><a rel=\"noreferrer noopener\" aria-label=\"MySQL Shell (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/mysql-shell\/8.0\/en\/\" target=\"_blank\">MySQL Shell<\/a><\/strong> &#8211; The MySQL Shell is an interactive <strong>Javascript<\/strong>, <strong>Python<\/strong>, or <strong>SQL<\/strong> interface supporting <strong>development<\/strong> and <strong>administration<\/strong> for the MySQL Server. You can use the MySQL Shell to perform data queries and updates as well as various administration operations.<\/li><li><strong>MySQL Connectors<\/strong> &#8211; Connectors that support the X Protocol and enable you to use X DevAPI in your chosen language (<em><strong><a rel=\"noreferrer noopener\" aria-label=\"Node.js (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/dev\/connector-nodejs\/8.0\/\" target=\"_blank\">Node.js<\/a><\/strong> &#8211; <strong>PHP<\/strong> &#8211; <strong><a rel=\"noreferrer noopener\" aria-label=\"Python (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/dev\/connector-python\/8.0\/\" target=\"_blank\">Python<\/a><\/strong> &#8211; <strong><a rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/dev\/connector-j\/8.0\/\" target=\"_blank\">Java<\/a><\/strong> &#8211; <strong><a rel=\"noreferrer noopener\" aria-label=\".NET (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/dev\/connector-net\/8.0\/\" target=\"_blank\">.NET<\/a><\/strong> &#8211; <\/em><strong><em><a rel=\"noreferrer noopener\" aria-label=\"C++ (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/dev\/connector-cpp\/8.0\/\" target=\"_blank\">C++<\/a>,&#8230;<\/em><\/strong>).<\/li><\/ul>\n\n\n\n\n\n<h2 class=\"wp-block-heading\">Write application using X DevAPI<\/h2>\n\n\n\n<p>As a disclaimer, I am not a developer, so sorry no fancy code in this blog post.<br>However the good news is that I can show you were you&rsquo;ll be able to found the best MySQL developer resources ever \ud83d\ude42 that is :<\/p>\n\n\n\n<p><a href=\"https:\/\/insidemysql.com\/\"><strong><em>https:\/\/insidemysql.com\/<\/em><\/strong><\/a><\/p>\n\n\n\n<p>And to start, I recommend to focus on the following articles:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Node.JS<\/strong><ul><li><a rel=\"noreferrer noopener\" aria-label=\"https:\/\/insidemysql.com\/introducing-connector-node-js-for-mysql-8-0\/ (opens in a new tab)\" href=\"https:\/\/insidemysql.com\/introducing-connector-node-js-for-mysql-8-0\/\" target=\"_blank\">https:\/\/insidemysql.com\/introducing-connector-node-js-for-mysql-8-0\/<\/a><\/li><\/ul><\/li><li><strong>Python<\/strong><ul><li><a rel=\"noreferrer noopener\" aria-label=\"https:\/\/insidemysql.com\/using-mysql-connector-python-8-0-with-mysql-8-0\/ (opens in a new tab)\" href=\"https:\/\/insidemysql.com\/using-mysql-connector-python-8-0-with-mysql-8-0\/\" target=\"_blank\">https:\/\/insidemysql.com\/using-mysql-connector-python-8-0-with-mysql-8-0\/<\/a><\/li><\/ul><\/li><li><strong>.NET<\/strong><ul><li><a rel=\"noreferrer noopener\" aria-label=\"https:\/\/insidemysql.com\/introducing-connector-net-with-full-support-for-mysql-8-0\/ (opens in a new tab)\" href=\"https:\/\/insidemysql.com\/introducing-connector-net-with-full-support-for-mysql-8-0\/\" target=\"_blank\">https:\/\/insidemysql.com\/introducing-connector-net-with-full-support-for-mysql-8-0\/<\/a><\/li><\/ul><\/li><li><strong>Java<\/strong><ul><li><a rel=\"noreferrer noopener\" aria-label=\"https:\/\/insidemysql.com\/connector-j-8-0-11-the-face-for-your-brand-new-document-oriented-database\/ (opens in a new tab)\" href=\"https:\/\/insidemysql.com\/connector-j-8-0-11-the-face-for-your-brand-new-document-oriented-database\/\" target=\"_blank\">https:\/\/insidemysql.com\/connector-j-8-0-11-the-face-for-your-brand-new-document-oriented-database\/<\/a><\/li><\/ul><\/li><li><strong>PHP<\/strong><ul><li><a rel=\"noreferrer noopener\" aria-label=\"https:\/\/insidemysql.com\/introducing-the-mysql-x-devapi-php-extension-for-mysql-8-0\/ (opens in a new tab)\" href=\"https:\/\/insidemysql.com\/introducing-the-mysql-x-devapi-php-extension-for-mysql-8-0\/\" target=\"_blank\">https:\/\/insidemysql.com\/introducing-the-mysql-x-devapi-php-extension-for-mysql-8-0\/<\/a><\/li><\/ul><\/li><li><strong>C++<\/strong><ul><li><a rel=\"noreferrer noopener\" aria-label=\"https:\/\/insidemysql.com\/what-is-new-in-connector-c-8-0\/ (opens in a new tab)\" href=\"https:\/\/insidemysql.com\/what-is-new-in-connector-c-8-0\/\" target=\"_blank\">https:\/\/insidemysql.com\/what-is-new-in-connector-c-8-0\/<\/a><\/li><\/ul><\/li><li><strong>ODBC<\/strong><ul><li><a rel=\"noreferrer noopener\" aria-label=\"https:\/\/insidemysql.com\/what-is-new-in-connector-odbc-8-0\/ (opens in a new tab)\" href=\"https:\/\/insidemysql.com\/what-is-new-in-connector-odbc-8-0\/\" target=\"_blank\">https:\/\/insidemysql.com\/what-is-new-in-connector-odbc-8-0\/<\/a><\/li><\/ul><\/li><\/ul>\n\n\n\n<p>And of course the newest articles as well.<br>Furthermore, another resource that would be useful to you is the<\/p>\n\n\n\n<p><a rel=\"noreferrer noopener\" aria-label=\"X DevAPI User Guide (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/x-devapi-userguide\/en\/\" target=\"_blank\"><strong><em>X DevAPI User Guide<\/em><\/strong><\/a><\/p>\n\n\n\n\n\n<h2 class=\"wp-block-heading\">Use Document Store with MySQL Shell<\/h2>\n\n\n\n<p>If you are a DBA, OPS and obviously a developer, the simplest way to use (or test) MySQL Document Store, is with MySQL Shell.<\/p>\n\n\n\n<p><a href=\"https:\/\/dev.mysql.com\/doc\/mysql-shell\/8.0\/en\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"MySQL Shell (opens in a new tab)\">MySQL Shell<\/a> is an integrated development &amp; administration shell where all MySQL products will be available through a common scripting interface. <br>If you don&rsquo;t know it yet, please <a rel=\"noreferrer noopener\" aria-label=\"download it (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/downloads\/shell\/\" target=\"_blank\">download it<\/a>. <br>Trust me you are going to love it !<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/dasini.net\/blog\/wp-content\/uploads\/MySQL_Shell_architecture.png\" alt=\"MySQL Shell\"><figcaption><br><\/figcaption><\/figure><\/div>\n\n\n\n<p>MySQL Shell key features are :<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Scripting for <strong>Javascript<\/strong>, <strong>Python<\/strong>, and <strong>SQL<\/strong> mode<\/li><li> Supports MySQL Standard and <strong>X Protocols<\/strong><\/li><li> <strong>Document<\/strong> and <strong>Relational<\/strong> Models<\/li><li> CRUD Document and Relational APIs via scripting<\/li><li> Traditional Table, JSON, Tab Separated output results formats<\/li><li> Both Interactive and Batch operations<\/li><\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Note:<\/p><p>MySQL Shell is also a key component of <a rel=\"noreferrer noopener\" aria-label=\"MySQL InnoDB Cluster (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/mysql-innodb-cluster-userguide.html\" target=\"_blank\"><strong>MySQL InnoDB Cluster<\/strong><\/a>. In this context, it allows you to deploy and manager a <a rel=\"noreferrer noopener\" aria-label=\"MySQL Group Replication (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/group-replication.html\" target=\"_blank\"><strong>MySQL Group Replication<\/strong><\/a> cluster.<\/p><p>See my <a rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\" href=\"http:\/\/dasini.net\/blog\/2018\/08\/30\/tutoriel-deployer-mysql-8-0-innodb-cluster\/\" target=\"_blank\">MySQL InnoDB  Cluster tutorial<\/a>.<\/p><\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">First steps with MySQL Shell<\/h3>\n\n\n\n<p>Let&rsquo;s connect to the MySQL Server with MySQL Shell (mysqlsh) <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ mysqlsh root@myHost\nMySQL Shell 8.0.15\n... snip ...\nYour MySQL connection id is 15 (X protocol)\nServer version: 8.0.15 MySQL Community Server - GPL\nNo default schema selected; type \\use &lt;schema> to set one.<\/code><\/pre>\n\n\n\n<p>We must be inside a X session in order to use MySQL as a document store. Luckily there is no extra step, because it&rsquo;s the default in MySQL 8.0. Note that the default \u00ab\u00a0X\u00a0\u00bb port is 33060.<br>You can check that you are inside a X session thus using X protocol<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ JS> session\n&lt;Session:root@myHost:33060>\n\nMySQL myHost:33060+ JS> \\status\n...snip...\n\nSession type:                 X\n\nDefault schema:               \nCurrent schema:               \nServer version:               8.0.15 MySQL Community Server - GPL\nProtocol version:             X protocol\n...snip...<\/code><\/pre>\n\n\n\n\n\n<p>If you are connected inside a classic session, you&rsquo;ll get the following input (note \u00ab\u00a0&lt;ClassicSession instead of &lt;Session\u00a0\u00bb) :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:3306 JS> session\n&lt;ClassicSession:root@myHost:3306><\/code><\/pre>\n\n\n\n<p>You can know what is you X protocol port by checking <a rel=\"noreferrer noopener\" aria-label=\"mysqlx_port (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/x-plugin-options-system-variables.html#sysvar_mysqlx_port\" target=\"_blank\">mysqlx_port<\/a> variable. <br>I&rsquo;ll switch to the MySQL Shell SQL mode to execute my SQL command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:3306 JS> \\sql\nSwitching to SQL mode... Commands end with ;\n\nMySQL myHost:3306 SQL> SHOW VARIABLES LIKE 'mysqlx_port';\n+---------------+-------+\n| Variable_name | Value |\n+---------------+-------+\n| mysqlx_port   | 33060 |\n+---------------+-------+<\/code><\/pre>\n\n\n\n<p>Then reconnect to the server using the right port (33060 by default) and you should be fine :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:3306 SQL> \\connect root@myHost:33060 \n...snip...\nYour MySQL connection id is 66 (X protocol)\nServer version: 8.0.15 MySQL Community Server - GPL\nNo default schema selected; type \\use &lt;schema> to set one.\n\nMySQL myHost:33060+ SQL> \\js\nSwitching to JavaScript mode...\n\nMySQL myHost:33060+ JS> session\n&lt;Session:root@myHost:33060><\/code><\/pre>\n\n\n\n\n\n<h3 class=\"wp-block-heading\">CRUD<\/h3>\n\n\n\n<p>We are going to create a schema (<em>demo<\/em>) where we will do our tests<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ JS> session.createSchema('demo')\n&lt;Schema:demo>\n\n\nMySQL myHost:33060+ JS> \\use demo\nDefault schema `demo` accessible through db.<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p><u>Note<\/u>:<\/p><p>The MySQL Shell default language is JavaScript. However, all the steps  described in this article can also be done in Python.<\/p><p>e.g. <\/p><p>JS&gt; session.createSchema(&lsquo;demo&rsquo;)  <\/p><p>Py&gt; session.create_schema(&lsquo;demo&rsquo;)<br><\/p><\/blockquote>\n\n\n\n<h4 class=\"wp-block-heading\">Create documents<\/h4>\n\n\n\n<p>Create a collection (<em>my_coll1<\/em>) insert the schema <em>demo<\/em> and insert documents :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.createCollection('my_coll1');\n&lt;Collection:my_coll1>\n\n\nMySQL myHost:33060+ demo JS> db.my_coll1.add({\"title\":\"MySQL Document Store\", \"abstract\":\"SQL is now optional!\", \"code\": \"42\"})\nQuery OK, 1 item affected (0.0358 sec)<\/code><\/pre>\n\n\n\n<p>Trying to add a <u>non valid<\/u> JSON document raise an error :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.my_coll1.add(\"This is not a valid JSON document\")\nCollectionAdd.add: Argument #1 expected to be a document, JSON expression or a list of documents (ArgumentError)<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"mce_31\">List collections<\/h4>\n\n\n\n<p>To get the list of collections belonging to the current schema use <a href=\"https:\/\/dev.mysql.com\/doc\/dev\/mysqlsh-api-javascript\/8.0\/classmysqlsh_1_1mysqlx_1_1_schema.html#aed56dce1764bf5e6beef21b0011372ee\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"getCollections (opens in a new tab)\">getCollections<\/a>() :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.getCollections()\n[\n    &lt;Collection:my_coll1>\n]<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"mce_32\">Find documents<\/h4>\n\n\n\n<p>Display the content of a collection with <a href=\"https:\/\/dev.mysql.com\/doc\/dev\/mysqlsh-api-javascript\/8.0\/classmysqlsh_1_1mysqlx_1_1_collection.html#ab0fa2263faab1ff0bdd40fbafe14808a\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"find (opens in a new tab)\">find<\/a>() :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.my_coll1.find()\n[\n    {\n        \"_id\": \"00005c9514e60000000000000053\",\n        \"code\": \"42\",\n        \"title\": \"MySQL Document Store\",\n        \"abstract\": \"SQL is now optional!\"\n    }\n]\n1 document in set (0.0029 sec)<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p><u>Note<\/u>:<\/p><p>Each document requires an identifier field called <strong><em>_id<\/em><\/strong>. The value of the _id field must be unique among all documents in the same collection. <br> MySQL server sets an _id value if the document does not contain the _id field.<\/p><p>Please read: <a rel=\"noreferrer noopener\" aria-label=\"Understanding Document IDs (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/x-devapi-userguide\/en\/understanding-automatic-document-ids.html\" target=\"_blank\">Understanding Document IDs<\/a>.<\/p><\/blockquote>\n\n\n\n<p>You can execute many operations on your document. One practical way to get the list of available functions is to press the <strong><em>&lt;TAB&gt;<\/em><\/strong> key, to ask for auto-completion, after the dot \u00ab\u00a0.\u00a0\u00bb<br>For example, type <strong>db.my_coll1.<\/strong> then press <strong><em>&lt;TAB&gt;<\/em><\/strong>twice, you&rsquo;ll get the following result:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.my_coll1.\nadd()               count()             dropIndex()         find()              getOne()            getSession()        modify()            remove()            replaceOne()        session\naddOrReplaceOne()   createIndex()       existsInDatabase()  getName()           getSchema()         help()              name                removeOne()         schema<\/code><\/pre>\n\n\n\n<p>You can also use the awesome MySQL Shell built-in help (I strongly recommend my colleague <a rel=\"noreferrer noopener\" aria-label=\"Jesper (opens in a new tab)\" href=\"https:\/\/twitter.com\/jwkrogh?lang=en\" target=\"_blank\">Jesper<\/a>&lsquo;s <a rel=\"noreferrer noopener\" aria-label=\"article (opens in a new tab)\" href=\"https:\/\/mysql.wisborg.dk\/2018\/08\/25\/mysql-shell-built-in-help\/\" target=\"_blank\">article<\/a>) and please <a rel=\"noreferrer noopener\" aria-label=\"bookmark is blog (opens in a new tab)\" href=\"https:\/\/mysql.wisborg.dk\/\" target=\"_blank\">bookmark is blog<\/a>.<br>Last but not least our documentations:  <a rel=\"noreferrer noopener\" aria-label=\"X DevAPI User Guide (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/x-devapi-userguide\/en\/\" target=\"_blank\">X DevAPI User Guide<\/a>, <a rel=\"noreferrer noopener\" aria-label=\"MySQL Shell JavaSCript API Reference (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/dev\/mysqlsh-api-javascript\/8.0\/\" target=\"_blank\">MySQL Shell JavaSCript API Reference<\/a> &amp; <a href=\"https:\/\/dev.mysql.com\/doc\/dev\/mysqlsh-api-python\/8.0\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"MySQL Shell Python API reference (opens in a new tab)\">MySQL Shell Python API reference<\/a>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"mce_5\">Modify documents<\/h4>\n\n\n\n<p>You&rsquo;ll need the <a href=\"https:\/\/dev.mysql.com\/doc\/dev\/mysqlsh-api-javascript\/8.0\/classmysqlsh_1_1mysqlx_1_1_collection.html#a31aaf6a98d9e1b57bf9c843d020fbda0\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"modify (opens in a new tab)\">modify<\/a>() function :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.my_coll1.find(\"_id='00005c9514e60000000000000053'\").fields(\"code\")\n[\n    {\n        \"code\": \"42\"\n    }\n]\n\n\nMySQL myHost:33060+ demo JS> db.my_coll1.modify(\"_id='00005c9514e60000000000000053'\").set(\"code\",\"2019\")\nQuery OK, 1 item affected (0.0336 sec)\nRows matched: 1  Changed: 1  Warnings: 0\n\n\nMySQL myHost:33060+ demo JS> db.my_coll1.find(\"_id='00005c9514e60000000000000053'\").fields(\"code\")\n[\n    {\n        \"code\": \"2019\"\n    }\n]<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"mce_7\">Remove content from documents<\/h4>\n\n\n\n<p>You can also modify the structure of a document by remove a key and its content with modify() and unset().<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.my_coll1.add({\"title\":\"Quote\", \"message\": \"Strive for greatness\"})\nQuery OK, 1 item affected (0.0248 sec)\n\nMySQL myHost:33060+ demo JS> db.my_coll1.find()\n[\n    {\n        \"_id\": \"00005c9514e60000000000000053\",\n        \"code\": \"42\",\n        \"title\": \"MySQL Document Store\",\n        \"abstract\": \"SQL is now optional!\"\n    },\n    {\n        \"_id\": \"00005c9514e60000000000000054\",\n        \"title\": \"Quote\",\n        \"message\": \"Strive for greatness\"\n    }\n]\n2 documents in set (0.0033 sec)\n\nMySQL myHost:33060+ demo JS> db.my_coll1.modify(\"_id='00005c9514e60000000000000054'\").unset(\"title\")\nQuery OK, 1 item affected (0.0203 sec)\n\nRows matched: 1  Changed: 1  Warnings: 0\n\nMySQL myHost:33060+ demo JS> db.my_coll1.find(\"_id='00005c9514e60000000000000054'\")\n[\n    {\n        \"_id\": \"00005c9514e60000000000000054\",\n        \"message\": \"Strive for greatness\"\n    }\n]<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"mce_7\">Remove documents<\/h4>\n\n\n\n<p>We are missing one last important operation, delete documents with <a href=\"https:\/\/dev.mysql.com\/doc\/dev\/mysqlsh-api-javascript\/8.0\/classmysqlsh_1_1mysqlx_1_1_collection.html#a84c51ef1a52dd959bf719a4b6092d317\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"remove (opens in a new tab)\">remove<\/a>()<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.my_coll1.remove(\"_id='00005c9514e60000000000000054'\")\nQuery OK, 1 item affected (0.0625 sec)\n\n\nMySQL myHost:33060+ demo JS> db.my_coll1.find(\"_id='00005c9514e60000000000000054'\")\nEmpty set (0.0003 sec)<\/code><\/pre>\n\n\n\n<p>You can also remove all documents in a collection with one command. To do so, use the remove(\u00ab\u00a0true\u00a0\u00bb) method without specifying any search condition.<br>Obviously it is usually not a good practice&#8230;<\/p>\n\n\n\n\n\n<h3 class=\"wp-block-heading\">Import JSON dcouments<\/h3>\n\n\n\n<p>Let&rsquo;s work with a bigger JSON collection.<br>MySQL Shell provide a very convenient tool, named <strong><a rel=\"noreferrer noopener\" aria-label=\"importJson (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/mysql-shell\/8.0\/en\/mysql-shell-utilities-json.html\" target=\"_blank\">importJson<\/a><\/strong>(), to easily <strong>import JSON documents inside your MySQL<\/strong> Server either in the form of collection or table.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.getCollections()\n[\n    &lt;Collection:my_coll1>\n]\n\n\nMySQL myHost:33060+ demo JS> util.importJson('GoT_episodes.json')\nImporting from file \"GoT_episodes.json\" to collection `demo`.`GoT_episodes` in MySQL Server at myHost:33060\n\n.. 73.. 73\nProcessed 47.74 KB in 73 documents in 0.1051 sec (694.75 documents\/s)\nTotal successfully imported documents 73 (694.75 documents\/s)\n\n\nMySQL myHost:33060+ demo JS> db.getCollections()\n[\n    &lt;Collection:GoT_episodes>, \n    &lt;Collection:my_coll1>\n]<\/code><\/pre>\n\n\n\n<p>You can find the JSON file source <a rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\" href=\"https:\/\/github.com\/jdorfman\/awesome-json-datasets#tv-shows\" target=\"_blank\">here<\/a>.<br>Note that I had to do an extra step before import the data:<br><strong>sed &lsquo;s\/}}},{\u00ab\u00a0id\u00a0\u00bb\/}}} {\u00ab\u00a0id\u00a0\u00bb\/g&rsquo;<\/strong> got_episodes.json.BAK > got_episodes.json<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>By the way you can <strong>import data from MongoDB to MySQL<\/strong> \\o\/<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a rel=\"noreferrer noopener\" aria-label=\"Importing Data from MongoDB to MySQL: BSON Data Types (opens in a new tab)\" href=\"https:\/\/mysqlserverteam.com\/importing-data-from-mongodb-to-mysql-bson-data-types\/\" target=\"_blank\">Importing Data from MongoDB to MySQL: BSON Data Types<\/a><\/li><li><a rel=\"noreferrer noopener\" aria-label=\"Importing Data from MongoDB to MySQL using JavaScript (opens in a new tab)\" href=\"https:\/\/mysqlserverteam.com\/importing-data-from-mongodb-to-mysql-using-javascript\/\" target=\"_blank\">Importing Data from MongoDB to MySQL using JavaScript<\/a><\/li><li><a rel=\"noreferrer noopener\" aria-label=\"Importing Data from MongoDB to MySQL using Python (opens in a new tab)\" href=\"https:\/\/mysqlserverteam.com\/importing-data-from-mongodb-to-mysql-using-python\/\" target=\"_blank\">Importing Data from MongoDB to MySQL using Python<\/a><\/li><li><a href=\"https:\/\/dev.mysql.com\/doc\/mysql-shell\/8.0\/en\/mysql-shell-utilities-json-bson.html\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Conversions for representations of BSON data types (opens in a new tab)\">Conversions for representations of BSON data types<\/a><\/li><\/ul>\n\n\n\n<p>No more excuses to finally get rid of MongoDB \ud83d\ude09<\/p>\n\n\n\n<p>Let&rsquo;s do some queries&#8230;<\/p>\n\n\n\n<p><u>Display 1 document<\/u><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.GoT_episodes.find().limit(1)\n[\n    {\n        \"id\": 4952,\n        \"_id\": \"00005c9514e6000000000000009e\",\n        \"url\": \"http:\/\/www.tvmaze.com\/episodes\/4952\/game-of-thrones-1x01-winter-is-coming\",\n        \"name\": \"Winter is Coming\",\n        \"image\": {\n            \"medium\": \"http:\/\/static.tvmaze.com\/uploads\/images\/medium_landscape\/1\/2668.jpg\",\n            \"original\": \"http:\/\/static.tvmaze.com\/uploads\/images\/original_untouched\/1\/2668.jpg\"\n        },\n        \"_links\": {\n            \"self\": {\n                \"href\": \"http:\/\/api.tvmaze.com\/episodes\/4952\"\n            }\n        },\n        \"number\": 1,\n        \"season\": 1,\n        \"airdate\": \"2011-04-17\",\n        \"airtime\": \"21:00\",\n        \"runtime\": 60,\n        \"summary\": \"&lt;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.&lt;\/p>\",\n        \"airstamp\": \"2011-04-18T01:00:00+00:00\"\n    }\n]<\/code><\/pre>\n\n\n\n<p>Looks like data relative to a <a href=\"https:\/\/www.hbo.com\/game-of-thrones\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"famous TV show (opens in a new tab)\">famous TV show<\/a> \ud83d\ude42<\/p>\n\n\n\n\n\n<p><u>All episodes from season 1<\/u><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.GoT_episodes.find(\"season=1\").fields(\"name\", \"summary\", \"airdate\").sort(\"number\")\n[\n    {\n        \"name\": \"Winter is Coming\",\n        \"airdate\": \"2011-04-17\",\n        \"summary\": \"&lt;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.&lt;\/p>\"\n    },\n    {\n        \"name\": \"The Kingsroad\",\n        \"airdate\": \"2011-04-24\",\n        \"summary\": \"&lt;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.&lt;\/p>\"\n    },\n    {\n        \"name\": \"Lord Snow\",\n        \"airdate\": \"2011-05-01\",\n        \"summary\": \"&lt;p>Jon Snow attempts to find his place amongst the Night's Watch. Eddard and his daughters arrive at King's Landing.&lt;\/p>\"\n    },\n    {\n        \"name\": \"Cripples, Bastards, and Broken Things\",\n        \"airdate\": \"2011-05-08\",\n        \"summary\": \"&lt;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.&lt;\/p>\"\n    },\n    {\n        \"name\": \"The Wolf and the Lion\",\n        \"airdate\": \"2011-05-15\",\n        \"summary\": \"&lt;p>Catelyn's actions on the road have repercussions for Eddard. Tyrion enjoys the dubious hospitality of the Eyrie.&lt;\/p>\"\n    },\n    {\n        \"name\": \"A Golden Crown\",\n        \"airdate\": \"2011-05-22\",\n        \"summary\": \"&lt;p>Viserys is increasingly frustrated by the lack of progress towards gaining his crown.&lt;\/p>\"\n    },\n    {\n        \"name\": \"You Win or You Die\",\n        \"airdate\": \"2011-05-29\",\n        \"summary\": \"&lt;p>Eddard's investigations in King's Landing reach a climax and a dark secret is revealed.&lt;\/p>\"\n    },\n    {\n        \"name\": \"The Pointy End\",\n        \"airdate\": \"2011-06-05\",\n        \"summary\": \"&lt;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.&lt;\/p>\"\n    },\n    {\n        \"name\": \"Baelor\",\n        \"airdate\": \"2011-06-12\",\n        \"summary\": \"&lt;p>Catelyn must negotiate with the irascible Lord Walder Frey.&lt;\/p>\"\n    },\n    {\n        \"name\": \"Fire and Blood\",\n        \"airdate\": \"2011-06-19\",\n        \"summary\": \"&lt;p>Daenerys must realize her destiny. Jaime finds himself in an unfamiliar predicament.&lt;\/p>\"\n    }\n]<\/code><\/pre>\n\n\n\n\n\n<p><u>First episode of each season<\/u><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.GoT_episodes.find(\"number=1\").fields(\"name\", \"airdate\", \"season\").sort(\"season\")\n[\n    {\n        \"name\": \"Winter is Coming\",\n        \"season\": 1,\n        \"airdate\": \"2011-04-17\"\n    },\n    {\n        \"name\": \"The North Remembers\",\n        \"season\": 2,\n        \"airdate\": \"2012-04-01\"\n    },\n    {\n        \"name\": \"Valar Dohaeris\",\n        \"season\": 3,\n        \"airdate\": \"2013-03-31\"\n    },\n    {\n        \"name\": \"Two Swords\",\n        \"season\": 4,\n        \"airdate\": \"2014-04-06\"\n    },\n    {\n        \"name\": \"The Wars to Come\",\n        \"season\": 5,\n        \"airdate\": \"2015-04-12\"\n    },\n    {\n        \"name\": \"The Red Woman\",\n        \"season\": 6,\n        \"airdate\": \"2016-04-24\"\n    },\n    {\n        \"name\": \"Dragonstone\",\n        \"season\": 7,\n        \"airdate\": \"2017-07-16\"\n    },\n    {\n        \"name\": \"TBA\",\n        \"season\": 8,\n        \"airdate\": \"2019-04-14\"\n    }\n]\n8 documents in set (0.0047 sec)<\/code><\/pre>\n\n\n\n\n\n<h3 class=\"wp-block-heading\">CRUD Prepared Statements<\/h3>\n\n\n\n<p>A common pattern with document store datastores is to repeatedly execute the same (or similar) kind of simple queries (e.g. \u00ab\u00a0<em>id<\/em>\u00a0\u00bb based lookup). <br>These queries can be <strong>accelerated using <\/strong><a rel=\"noreferrer noopener\" aria-label=\"prepared CRUD statements (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/x-devapi-userguide\/en\/parameter-binding.html#preparing-crud-statements\" target=\"_blank\"><strong>prepared (CRUD) statements<\/strong><\/a>.<\/p>\n\n\n\n<p>For example if your application often use the following query:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.GoT_episodes.find(\"number=1 AND season=1\").fields(\"name\", \"airdate\")\n[\n    {\n        \"name\": \"Winter is Coming\",\n        \"airdate\": \"2011-04-17\"\n    }\n]<\/code><\/pre>\n\n\n\n<p>So it&rsquo;s probably a good idea to use prepared statements.<br>First we need to prepare the query:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Prepare a statement using a named parameter\nvar gotEpisode = db.GoT_episodes.find(\"number = :episodeNum AND season = :seasonNum\").fields(\"name\", \"airdate\")<\/code><\/pre>\n\n\n\n<p>Then bind the value to the parameter :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> gotEpisode.bind('episodeNum', 1).bind('seasonNum', 1)\n[\n    {\n        \"name\": \"Winter is Coming\",\n        \"airdate\": \"2011-04-17\"\n    }\n]<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> gotEpisode.bind('episodeNum', 7).bind('seasonNum', 3)\n[\n    {\n        \"name\": \"The Bear and the Maiden Fair\",\n        \"airdate\": \"2013-05-12\"\n    }\n]<\/code><\/pre>\n\n\n\n<p>Simply powerful!<\/p>\n\n\n\n\n\n<h3 class=\"wp-block-heading\" id=\"mce_57\">Index<\/h3>\n\n\n\n<p>Indeed relevant indexes is a common practice to improve performances. <strong>MySQL Document Store allows you to index your keys<\/strong> inside the JSON document.<\/p>\n\n\n\n<p><u>Add a composite Index on keys <em>season<\/em> AND <em>episode<\/em>.<\/u><br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>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}]})\nQuery OK, 0 rows affected (0.1245 sec)<\/code><\/pre>\n\n\n\n<p>The <strong><em>required: true<\/em><\/strong> option means that it&rsquo;s mandatory for all documents to contains at least the keys <em>number<\/em> and <em>season<\/em>.<br>E.g.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.GoT_episodes.add({\"name\": \"MySQL 8 is Great\"})\nERROR: 5115: Document is missing a required field\n\n\nMySQL myHost:33060+ demo JS> db.GoT_episodes.add({\"name\": \"MySQL 8 is Great\", \"number\": 8})\nERROR: 5115: Document is missing a required field\n\n\nMySQL myHost:33060+ demo JS> db.GoT_episodes.add({\"name\": \"MySQL 8 is Great\", \"season\": 8})\nERROR: 5115: Document is missing a required field<\/code><\/pre>\n\n\n\n\n\n<p><u>Add an index on key summary<\/u> (30 first characters)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.GoT_episodes.createIndex('idxSummary', {fields: [{field: \"$.summary\", type: \"TEXT(30)\"}]})\nQuery OK, 0 rows affected (0.1020 sec)<\/code><\/pre>\n\n\n\n\n\n<p><u>Add a Unique Index on key <em>id<\/em><\/u> <br>Not the one generated by MySQL called _id and already indexed (primary key)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.GoT_episodes.createIndex('idxId', {fields: [{field: \"$.id\", type: \"INT UNSIGNED\"}], unique: true})\nQuery OK, 0 rows affected (0.3379 sec)<\/code><\/pre>\n\n\n\n<p>The <strong><em>unique: true<\/em><\/strong> option means that values of key <em>id<\/em> must be unique for each document inside the collection. i.e. no duplicate values.<br>E.g.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.GoT_episodes.add({\"id\":4952, \"number\": 42, \"season\": 42 })\nERROR: 5116: Document contains a field value that is not unique but required to be<\/code><\/pre>\n\n\n\n<p>You can obviously drop an index, using <a rel=\"noreferrer noopener\" aria-label=\"dropIndex (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/dev\/mysqlsh-api-javascript\/8.0\/classmysqlsh_1_1mysqlx_1_1_collection.html#a1e4afe634167522ca8d9792d11914ac0\" target=\"_blank\">dropIndex<\/a>().<br>E.g. db.GoT_episodes.dropIndex(\u00ab\u00a0idxSummary\u00a0\u00bb)<\/p>\n\n\n\n\n\n<h3 class=\"wp-block-heading\" id=\"mce_66\">Transactions<\/h3>\n\n\n\n<p><strong>MySQL Document Store<\/strong> is full <strong><a rel=\"noreferrer noopener\" aria-label=\"ACID (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/glossary.html#glos_acid\" target=\"_blank\">ACID<\/a><\/strong>, it relies on the proven <a rel=\"noreferrer noopener\" aria-label=\"InnoDB (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/innodb-storage-engine.html\" target=\"_blank\"><strong>InnoDB<\/strong><\/a>\u2019s strength &amp; robustness.<\/p>\n\n\n\n<p>Yes, you get it right, <strong>We do care about your data<\/strong>!<\/p>\n\n\n\n<p>You need the functions below:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a rel=\"noreferrer noopener\" aria-label=\"StartTransaction (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/dev\/mysqlsh-api-javascript\/8.0\/classmysqlsh_1_1mysqlx_1_1_session.html#ab2a7f1cc213c7ad38c82969c602ed6ad\" target=\"_blank\">startTransaction<\/a>()<\/li><li><a rel=\"noreferrer noopener\" aria-label=\"commit (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/dev\/mysqlsh-api-javascript\/8.0\/classmysqlsh_1_1mysqlx_1_1_session.html#ad55316f5135cdae6aa6c5a763f6c3473\" target=\"_blank\">commit<\/a>()<\/li><li><a rel=\"noreferrer noopener\" aria-label=\"rollback (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/dev\/mysqlsh-api-javascript\/8.0\/classmysqlsh_1_1mysqlx_1_1_session.html#a071de472f6ac976c658e4643f3fb3d0c\" target=\"_blank\">rollback<\/a>()<\/li><\/ul>\n\n\n\n<p>Let&rsquo;s see an example with a multi collection transactions that will be rollback.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Start the transaction\nsession.startTransaction()\n\nMySQL myHost:33060+ demo JS> db.my_coll1.find()\n[\n    {\n        \"_id\": \"00005c9514e60000000000000053\",\n        \"code\": \"42\",\n        \"title\": \"MySQL Document Store\",\n        \"abstract\": \"SQL is now optional!\"\n    }\n]\n1 document in set (0.0033 sec)\n\n\n\/\/ Modify a document in collection my_coll1\nMySQL myHost:33060+ demo JS> db.my_coll1.modify(\"_id = '00005c9514e60000000000000053'\").unset(\"code\")\nQuery OK, 1 item affected (0.0043 sec)\nRows matched: 1  Changed: 1  Warnings: 0\n\n\n\/\/Collection 1 : my_coll1\n\/\/ Add a new document in my_coll1\nMySQL myHost:33060+ demo JS> db.my_coll1.add({\"title\":\"Quote\", \"message\": \"Be happy, be bright, be you\"})\nQuery OK, 1 item affected (0.0057 sec)\n\n\nMySQL myHost:33060+ demo JS> db.my_coll1.find()\n[\n    {\n        \"_id\": \"00005c9514e60000000000000053\",\n        \"title\": \"MySQL Document Store\",\n        \"abstract\": \"SQL is now optional!\"\n    },\n    {\n        \"_id\": \"00005c9514e600000000000000e7\",\n        \"title\": \"Quote\",\n        \"message\": \"Be happy, be bright, be you\"\n    }\n]\n2 documents in set (0.0030 sec)\n\n\n\n\/\/ Collection 2 : GoT_episodes\n\/\/ Number of documents in GoT_episodes\nMySQL myHost:33060+ demo JS> db.GoT_episodes.count()\n73\n\n\n\/\/ Remove all the 73 documents from GoT_episodes\nMySQL myHost:33060+ demo JS> db.GoT_episodes.remove(\"true\")\nQuery OK, 73 items affected (0.2075 sec)\n\n\n\/\/ Empty collection\nMySQL myHost:33060+ demo JS> db.GoT_episodes.count()\n0\n\n\n\n\/\/ Finally want my previous status back\n\/\/ Rollback the transaction (if necessary e.g. in case of an error)\nMySQL myHost:33060+ demo JS> session.rollback() \nQuery OK, 0 rows affected (0.0174 sec)<\/code><\/pre>\n\n\n\n<p>Tadam!!!<br>We back in the past \ud83d\ude42<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.my_coll1.find()\n[\n    {\n        \"_id\": \"00005c9514e60000000000000053\",\n        \"code\": \"42\",\n        \"title\": \"MySQL Document Store\",\n        \"abstract\": \"SQL is now optional!\"\n    }\n]\n1 document in set (0.0028 sec)\n\n\nMySQL myHost:33060+ demo JS> db.GoT_episodes.count()\n73<\/code><\/pre>\n\n\n\n\n\n<h3 class=\"wp-block-heading\" id=\"mce_88\">Execute (complex) SQL queries<\/h3>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/dasini.net\/blog\/wp-content\/uploads\/NoSQL_%2B_SQL_MySQL%3D.png\" alt=\"NoSQL + SQL = MySQL\"><figcaption><br><\/figcaption><\/figure><\/div>\n\n\n\n<p>From the MySQL server point of view, <u>collections are tables<\/u> as well, like regular tables.<br>And this is very powerful !!!<\/p>\n\n\n\n<p>Powerful because that allow you, within the same datastore (MySQL), to do <u>CRUD queries <strong>and<\/strong> SQL queries on the same dataset<\/u>.<br>Powerful because that allow you, to have your <u>OLTP CRUD workload <strong>and<\/strong> your analytics SQL workload at the same place<\/u>.<br>So no need to transfer\/sync\/&#8230; data from 1 datastore to another anymore!!!<\/p>\n\n\n\n<p>You can do SQL queries using <a rel=\"noreferrer noopener\" aria-label=\"sql (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/dev\/mysqlsh-api-javascript\/8.0\/classmysqlsh_1_1mysqlx_1_1_session.html#a5419a6f304134416d025c65f7a9ff0dd\" target=\"_blank\">sql<\/a>() functions:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> session.sql(\"SELECT count(*) FROM GoT_episodes\")\n+----------+\n| count(*) |\n+----------+\n|       73 |\n+----------+<\/code><\/pre>\n\n\n\n<p>You can also do SQL queries just as you have done until now, using the rich set of <a rel=\"noreferrer noopener\" aria-label=\"MySQL JSON functions (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/json-functions.html\" target=\"_blank\">MySQL JSON functions<\/a>.<br>OK let&rsquo;s have a closer look.<\/p>\n\n\n\n<p>Remember this CRUD query?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.GoT_episodes.find(\"number=1 AND season=1\").fields(\"name\", \"airdate\")\n[\n    {\n        \"name\": \"Winter is Coming\",\n        \"airdate\": \"2011-04-17\"\n    }\n]<\/code><\/pre>\n\n\n\n<p>Its SQL query alter ego is :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> \\sql\n\nMySQL myHost:33060+ demo SQL> \nSELECT doc->>\"$.name\" AS name, doc->>\"$.airdate\" AS airdate \nFROM GoT_episodes \nWHERE doc->>\"$.number\" = 1 AND doc->>\"$.season\" = 1\\G\n*************************** 1. row ***************************\n   name: Winter is Coming\nairdate: 2011-04-17<\/code><\/pre>\n\n\n\n\n\n<p>Let\u2019s do some SQL queries\u2026<\/p>\n\n\n\n<p><u>Number of episodes by season<\/u><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo SQL> \nSELECT doc->>\"$.season\", COUNT(doc->>\"$.number\") \nFROM GoT_episodes \nGROUP BY doc->>\"$.season\";\n+------------------+-------------------------+\n| doc->>\"$.season\" | count(doc->>\"$.number\") |\n+------------------+-------------------------+\n| 1                |                      10 |\n| 2                |                      10 |\n| 3                |                      10 |\n| 4                |                      10 |\n| 5                |                      10 |\n| 6                |                      10 |\n| 7                |                       7 |\n| 8                |                       6 |\n+------------------+-------------------------+<\/code><\/pre>\n\n\n\n\n\n<p><u>Episode statistics for each season<\/u><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo SQL> \nSELECT DISTINCT\n    doc->>\"$.season\" AS Season,\n    max(doc->>\"$.runtime\") OVER w AS \"Max duration\",\n    min(doc->>\"$.runtime\") OVER w AS \"Min duration\",\n    AVG(doc->>\"$.runtime\") OVER w AS \"Avg duration\"\nFROM GoT_episodes\nWINDOW w AS (\n    PARTITION BY doc->>\"$.season\"\n    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING\n);\n+--------+--------------+--------------+--------------+\n| Season | Max duration | Min duration | Avg duration |\n+--------+--------------+--------------+--------------+\n| 1      | 60           | 60           |           60 |\n| 2      | 60           | 60           |           60 |\n| 3      | 60           | 60           |           60 |\n| 4      | 60           | 60           |           60 |\n| 5      | 60           | 60           |           60 |\n| 6      | 69           | 60           |         60.9 |\n| 7      | 60           | 60           |           60 |\n| 8      | 90           | 60           |           80 |\n+--------+--------------+--------------+--------------+<\/code><\/pre>\n\n\n\n\n\n<p><u>Statistics on the number of days between episodes<\/u><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo SQL> \nSELECT\n    doc->>\"$.airdate\" AS airdate, \n    DATEDIFF(doc->>\"$.airdate\", lag(doc->>\"$.airdate\") OVER w) AS \"Delta days between episode\",\n    DATEDIFF(doc->>\"$.airdate\", first_value(doc->>\"$.airdate\") OVER w) AS \"Total days since 1st episode\"\nFROM GoT_episodes\n    WINDOW w AS (ORDER BY doc->>\"$.airdate\")\n;\n+------------+----------------------------+------------------------------+\n| airdate    | Delta days between episode | Total days since 1st episode |\n+------------+----------------------------+------------------------------+\n| 2011-04-17 |                       NULL |                            0 |\n| 2011-04-24 |                          7 |                            7 |\n| 2011-05-01 |                          7 |                           14 |\n| 2011-05-08 |                          7 |                           21 |\n| 2011-05-15 |                          7 |                           28 |\n| 2011-05-22 |                          7 |                           35 |\n| 2011-05-29 |                          7 |                           42 |\n| 2011-06-05 |                          7 |                           49 |\n| 2011-06-12 |                          7 |                           56 |\n| 2011-06-19 |                          7 |                           63 |\n| 2012-04-01 |                        287 |                          350 |\n| 2012-04-08 |                          7 |                          357 |\n| 2012-04-15 |                          7 |                          364 |\n| 2012-04-22 |                          7 |                          371 |\n| 2012-04-29 |                          7 |                          378 |\n| 2012-05-06 |                          7 |                          385 |\n| 2012-05-13 |                          7 |                          392 |\n| 2012-05-20 |                          7 |                          399 |\n| 2012-05-27 |                          7 |                          406 |\n| 2012-06-03 |                          7 |                          413 |\n| 2013-03-31 |                        301 |                          714 |\n| 2013-04-07 |                          7 |                          721 |\n| 2013-04-14 |                          7 |                          728 |\n| 2013-04-21 |                          7 |                          735 |\n| 2013-04-28 |                          7 |                          742 |\n| 2013-05-05 |                          7 |                          749 |\n| 2013-05-12 |                          7 |                          756 |\n| 2013-05-19 |                          7 |                          763 |\n| 2013-06-02 |                         14 |                          777 |\n| 2013-06-09 |                          7 |                          784 |\n| 2014-04-06 |                        301 |                         1085 |\n| 2014-04-13 |                          7 |                         1092 |\n| 2014-04-20 |                          7 |                         1099 |\n| 2014-04-27 |                          7 |                         1106 |\n| 2014-05-04 |                          7 |                         1113 |\n| 2014-05-11 |                          7 |                         1120 |\n| 2014-05-18 |                          7 |                         1127 |\n| 2014-06-01 |                         14 |                         1141 |\n| 2014-06-08 |                          7 |                         1148 |\n| 2014-06-15 |                          7 |                         1155 |\n| 2015-04-12 |                        301 |                         1456 |\n| 2015-04-19 |                          7 |                         1463 |\n| 2015-04-26 |                          7 |                         1470 |\n| 2015-05-03 |                          7 |                         1477 |\n| 2015-05-10 |                          7 |                         1484 |\n| 2015-05-17 |                          7 |                         1491 |\n| 2015-05-24 |                          7 |                         1498 |\n| 2015-05-31 |                          7 |                         1505 |\n| 2015-06-07 |                          7 |                         1512 |\n| 2015-06-14 |                          7 |                         1519 |\n| 2016-04-24 |                        315 |                         1834 |\n| 2016-05-01 |                          7 |                         1841 |\n| 2016-05-08 |                          7 |                         1848 |\n| 2016-05-15 |                          7 |                         1855 |\n| 2016-05-22 |                          7 |                         1862 |\n| 2016-05-29 |                          7 |                         1869 |\n| 2016-06-05 |                          7 |                         1876 |\n| 2016-06-12 |                          7 |                         1883 |\n| 2016-06-19 |                          7 |                         1890 |\n| 2016-06-26 |                          7 |                         1897 |\n| 2017-07-16 |                        385 |                         2282 |\n| 2017-07-23 |                          7 |                         2289 |\n| 2017-07-30 |                          7 |                         2296 |\n| 2017-08-06 |                          7 |                         2303 |\n| 2017-08-13 |                          7 |                         2310 |\n| 2017-08-20 |                          7 |                         2317 |\n| 2017-08-27 |                          7 |                         2324 |\n| 2019-04-14 |                        595 |                         2919 |\n| 2019-04-21 |                          7 |                         2926 |\n| 2019-04-28 |                          7 |                         2933 |\n| 2019-05-05 |                          7 |                         2940 |\n| 2019-05-12 |                          7 |                         2947 |\n| 2019-05-19 |                          7 |                         2954 |\n+------------+----------------------------+------------------------------+\n73 rows in set (0.0066 sec)<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p><u>Note<\/u>:<\/p><p>Hey buddy, aren&rsquo;t <strong>Window Functions<\/strong> very cool?<\/p><p>More <a rel=\"noreferrer noopener\" aria-label=\"here (opens in a new tab)\" href=\"https:\/\/mysqlserverteam.com\/mysql-8-0-2-introducing-window-functions\/\" target=\"_blank\">here<\/a> and <a rel=\"noreferrer noopener\" aria-label=\"here (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/window-functions.html\" target=\"_blank\">here<\/a>.<\/p><\/blockquote>\n\n\n\n\n\n<h3 class=\"wp-block-heading\" id=\"mce_101\">Drop collections<\/h3>\n\n\n\n<p>Use <a href=\"https:\/\/dev.mysql.com\/doc\/dev\/mysqlsh-api-javascript\/8.0\/classmysqlsh_1_1mysqlx_1_1_schema.html#aac366d63172f96ccf2e6f131eba3a7e5\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"dropCollection (opens in a new tab)\">dropCollection<\/a>() :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MySQL myHost:33060+ demo JS> db.getCollections()\n[\n    &lt;Collection:GoT_episodes>, \n    &lt;Collection:my_coll1>\n]\n\n\nMySQL myHost:33060+ demo JS> db.dropCollection(\"my_coll1\")\nMySQL myHost:33060+ demo JS> db.getCollections()\n[\n    &lt;Collection:GoT_episodes>\n]<\/code><\/pre>\n\n\n\n\n\n<h2 class=\"wp-block-heading\" id=\"mce_6\">Conclusion<\/h2>\n\n\n\n<p>Wow!<br>Probably one of my longest article, but I wanted to be sure to give you a large overview of <strong>MySQL Document Store<\/strong> (although not exhaustive) from a point of view of a non developer.<\/p>\n\n\n\n<p><br>Now it is your turn to give it a try \ud83d\ude42<\/p>\n\n\n\n<p style=\"text-align:center\" class=\"has-text-color has-large-font-size has-vivid-red-color\"><strong>NoSQL + SQL = MySQL<\/strong><\/p>\n\n\n\n\n\n<h2 class=\"wp-block-heading\" id=\"mce_0\">In order to go further<\/h2>\n\n\n\n<p>Some useful link:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a rel=\"noreferrer noopener\" aria-label=\"Top 10 reasons for NoSQL with MySQL (opens in a new tab)\" href=\"https:\/\/lefred.be\/content\/top-10-reasons-for-nosql-with-mysql\/\" target=\"_blank\">Top 10 reasons for NoSQL with MySQL<\/a><\/li><li><a rel=\"noreferrer noopener\" aria-label=\"MySQL Document Store Overview (opens in a new tab)\" href=\"https:\/\/www.mysql.com\/products\/enterprise\/document_store.html\" target=\"_blank\">MySQL Document Store Overview<\/a> <\/li><li><a href=\"https:\/\/www.mysql.com\/news-and-events\/web-seminars\/moving-to-the-future-from-mongodb-to-mysql-document-store\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Moving to the Future from MongoDB to MySQL Document Store (opens in a new tab)\">Moving to the Future from MongoDB to MySQL Document Store<\/a> <\/li><li><a rel=\"noreferrer noopener\" aria-label=\"Using MySQL as a Document Store (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/document-store.html\" target=\"_blank\">Using MySQL as a Document Store<\/a> <\/li><li><a rel=\"noreferrer noopener\" aria-label=\"MySQL Engineering Blog (opens in a new tab)\" href=\"https:\/\/insidemysql.com\/\" target=\"_blank\">MySQL Engineering Blog<\/a> <\/li><li><a rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/x-devapi-userguide\/en\/\" target=\"_blank\">X DevAPI User Guide<\/a> <\/li><li><a rel=\"noreferrer noopener\" href=\"https:\/\/dev.mysql.com\/doc\/dev\/mysqlsh-api-javascript\/8.0\/\" target=\"_blank\">MySQL Shell JavaSCript API Reference<\/a> <\/li><li><a rel=\"noreferrer noopener\" href=\"https:\/\/dev.mysql.com\/doc\/dev\/mysqlsh-api-python\/8.0\/\" target=\"_blank\">MySQL Shell Python API reference<\/a> <\/li><li><a rel=\"noreferrer noopener\" aria-label=\"X plugin (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/x-plugin.html\" target=\"_blank\">X plugin<\/a> <\/li><li><a rel=\"noreferrer noopener\" aria-label=\"X plugin (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/x-plugin.html\" target=\"_blank\">X protocol<\/a> <\/li><li><a rel=\"noreferrer noopener\" aria-label=\"MySQL Shell (opens in a new tab)\" href=\"https:\/\/dev.mysql.com\/doc\/mysql-shell\/8.0\/en\/\" target=\"_blank\">MySQL Shell<\/a> <\/li><\/ul>\n\n\n\n\n\n<div style=\"height:75px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"has-vivid-red-color has-text-color\"><strong>Thanks for using MySQL!<\/strong><\/p>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p><a href=\"https:\/\/www.linkedin.com\/groups\/12524512\/\" target=\"_blank\" rel=\"noopener\" title=\"Olivier DASINI on Linkedin\">Follow me on Linkedin<\/a><\/p>\n\n\n\n<p>Watch my videos on my <a href=\"https:\/\/www.youtube.com\/channel\/UC12TulyJsJZHoCmby3Nm3WQ\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"Olivier's MySQL Channel\">YouTube channel<\/a> and <a href=\"https:\/\/www.youtube.com\/channel\/UC12TulyJsJZHoCmby3Nm3WQ\/?sub_confirmation=1\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"Subscribe\">subscribe<\/a>.<\/p>\n\n\n\n<p>My <a href=\"https:\/\/www.slideshare.net\/freshdaz\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"Olivier DASINI on Slideshare\">Slideshare account<\/a>.<\/p>\n\n\n\n<p>My <a href=\"https:\/\/speakerdeck.com\/freshdaz\/\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"Olivier DASINI on Speaker Deck\">Speaker Deck account<\/a>.<\/p>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"has-vivid-red-color has-text-color\"><strong>Thanks for using HeatWave &amp; MySQL!<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p> MySQL 8.0 provides another way to handle JSON documents,  actually in a \u00ab\u00a0Not only SQL\u00a0\u00bb (NoSQL) approach&#8230;<br \/>\nIn 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!<br \/>\nDid you know that?<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"footnotes":""},"categories":[403,257,203,425,339],"tags":[742,415,310,743,312,828],"class_list":["post-2874","post","type-post","status-publish","format-standard","hentry","category-document-store","category-json","category-mysql-en","category-nosql-en","category-tuto-en","tag-crud","tag-document-store-en","tag-json-en","tag-mongodb","tag-nosql-en","tag-window-functions"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p9LfWW-Km","jetpack-related-posts":[{"id":2465,"url":"https:\/\/dasini.net\/blog\/2018\/07\/23\/30-mins-with-mysql-json-functions\/","url_meta":{"origin":2874,"position":0},"title":"30 mins with MySQL JSON functions","author":"Olivier DASINI","date":"23 juillet 2018","format":false,"excerpt":"JSON (JavaScript Object Notation) is a popular way for moving data between various systems, including databases. Starting with 5.7 MySQL implemented a native JSON data type and a set of JSON functions that allows you to perform operations on JSON values.","rel":"","context":"Dans &quot;json&quot;","block_context":{"text":"json","link":"https:\/\/dasini.net\/blog\/category\/json\/"},"img":{"alt_text":"MySQL native JSON data type","src":"https:\/\/i0.wp.com\/dasini.net\/blog\/wp-content\/uploads\/json_icon.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":8442,"url":"https:\/\/dasini.net\/blog\/2025\/10\/14\/querying-the-unstructured-natural-language-to-sql-for-json-data\/","url_meta":{"origin":2874,"position":1},"title":"Querying the Unstructured: Natural Language to SQL for JSON Data","author":"Olivier DASINI","date":"14 octobre 2025","format":false,"excerpt":"Bridging natural language processing with semi-structured data brings both opportunity and complexity. MySQL HeatWave GenAI\u2019s NL2SQL feature shows how natural language can simplify data interaction \u2014 even for JSON documents. Yet, because JSON embeds both data and metadata within a single column, LLMs may struggle without explicit schema cues. By\u2026","rel":"","context":"Dans &quot;AI&quot;","block_context":{"text":"AI","link":"https:\/\/dasini.net\/blog\/category\/ai\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/dasini.net\/blog\/wp-content\/uploads\/2025\/10\/Querying-the-Unstructured-Natural-Language-to-SQL-for-JSON-Data-400.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":2443,"url":"https:\/\/dasini.net\/blog\/2018\/07\/12\/plenty-of-new-mysql-books\/","url_meta":{"origin":2874,"position":2},"title":"Plenty of new MySQL books","author":"Olivier DASINI","date":"12 juillet 2018","format":false,"excerpt":"In the old days, when we wanted to strengthen our skills the only option was to buy a good book. Nowadays one can find a lot of resources on the Internet, however quality is often poor. Fortunately there are still some great people who are brave enough to write new\u2026","rel":"","context":"Dans &quot;Book&quot;","block_context":{"text":"Book","link":"https:\/\/dasini.net\/blog\/category\/book\/"},"img":{"alt_text":"MySQL and JSON: A Practical Programming Guide - Discover how to use JavaScript Object Notation (JSON) with MySQL","src":"https:\/\/i0.wp.com\/images-na.ssl-images-amazon.com\/images\/I\/416UKa-bH%2BL._SX332_BO1%2C204%2C203%2C200_.jpg?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":1515,"url":"https:\/\/dasini.net\/blog\/2015\/11\/17\/30-mins-with-json-in-mysql\/","url_meta":{"origin":2874,"position":3},"title":"30 mins with JSON in MySQL","author":"Olivier DASINI","date":"17 novembre 2015","format":false,"excerpt":"MySQL 5.7 is GA and has over than 150 new features. One of them is a Native JSON Data Type and JSON Functions: \"Allows for efficient and flexible storage, search and manipulation of schema-less data. Enhancements include a new internal binary format, support for easy integration within SQL, and index\u2026","rel":"","context":"Dans &quot;json&quot;","block_context":{"text":"json","link":"https:\/\/dasini.net\/blog\/category\/json\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":4151,"url":"https:\/\/dasini.net\/blog\/2020\/12\/17\/mysql-shell-the-new-era\/","url_meta":{"origin":2874,"position":4},"title":"MySQL SHELL &#8211; The new era","author":"Anastasia Papachristopoulou","date":"17 d\u00e9cembre 2020","format":false,"excerpt":"In one of our previous articles - Setting up Replication with various methods for MySQL 8 - we reviewed how to create a replica with multiple tools. Now, it is time to perform the same action but with MySQL Shell.","rel":"","context":"Dans &quot;Backup \/ Restore&quot;","block_context":{"text":"Backup \/ Restore","link":"https:\/\/dasini.net\/blog\/category\/backup-restore\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":5556,"url":"https:\/\/dasini.net\/blog\/2022\/03\/09\/data-migration-from-mariadb-to-mysql\/","url_meta":{"origin":2874,"position":5},"title":"Data Migration from MariaDB to MySQL","author":"Olivier DASINI","date":"9 mars 2022","format":false,"excerpt":"Yet another customer wanted to migrate from MariaDB to MySQL. So I decided to write down the overall data migration process. Indeed each migration are a unique story so I won\u2019t provide you a \u201cHow to migrate\u201d\u2026 The idea is to highlight the general path and help you to avoid\u2026","rel":"","context":"Dans &quot;Cloud&quot;","block_context":{"text":"Cloud","link":"https:\/\/dasini.net\/blog\/category\/cloud\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/dasini.net\/blog\/wp-content\/uploads\/2022\/03\/MySQL_Shell_Overview.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/dasini.net\/blog\/wp-content\/uploads\/2022\/03\/MySQL_Shell_Overview.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/dasini.net\/blog\/wp-content\/uploads\/2022\/03\/MySQL_Shell_Overview.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/dasini.net\/blog\/wp-content\/uploads\/2022\/03\/MySQL_Shell_Overview.png?resize=700%2C400&ssl=1 2x"},"classes":[]}],"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/dasini.net\/blog\/wp-json\/wp\/v2\/posts\/2874","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dasini.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dasini.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dasini.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/dasini.net\/blog\/wp-json\/wp\/v2\/comments?post=2874"}],"version-history":[{"count":66,"href":"https:\/\/dasini.net\/blog\/wp-json\/wp\/v2\/posts\/2874\/revisions"}],"predecessor-version":[{"id":2949,"href":"https:\/\/dasini.net\/blog\/wp-json\/wp\/v2\/posts\/2874\/revisions\/2949"}],"wp:attachment":[{"href":"https:\/\/dasini.net\/blog\/wp-json\/wp\/v2\/media?parent=2874"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dasini.net\/blog\/wp-json\/wp\/v2\/categories?post=2874"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dasini.net\/blog\/wp-json\/wp\/v2\/tags?post=2874"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}