0% found this document useful (0 votes)
124 views

Working With JSON in MySQL - Scotch

This document discusses working with JSON data in MySQL databases. It explains that SQL databases are rigid in their structure, while NoSQL databases are flexible and schema-less. It then provides an overview of how to store and query JSON documents in MySQL, including inserting, updating, and selecting JSON data using functions like JSON_SET(), JSON_INSERT(), and JSON_EXTRACT().

Uploaded by

ehsan.amimul3795
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
124 views

Working With JSON in MySQL - Scotch

This document discusses working with JSON data in MySQL databases. It explains that SQL databases are rigid in their structure, while NoSQL databases are flexible and schema-less. It then provides an overview of how to store and query JSON documents in MySQL, including inserting, updating, and selecting JSON data using functions like JSON_SET(), JSON_INSERT(), and JSON_EXTRACT().

Uploaded by

ehsan.amimul3795
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 40

Write(https://pub.scotch.io/write) Slack(http://slack.scotch.io) Shop(http://shop.scotch.

io)
Topshelfwebdevelopertraining.
About(https://scotch.io/about) Login/Register

Menu
scotch
(https://scotch.io)
Subscribe & get our FREE eBook
Build Your First Node.js App

Email Address

Free Node Book

Stalk Us


(https://twitter.com/scotch_io)
laravel(https://scotch.io/tag/laravel) php(https://scotch.io/tag/php)


Working with JSON in (https://www.facebook.com/scotchdeve

MySQL
(https://github.com/scotch-io)
LearnhowtouseandqueryJSONdatainyour
MYSQLdatabases.

(https://feeds.feedblitz.com/scotch_io)
(https://pub.scotch.io/@nomanurrehman)

NomanUrRehman (https://pub.scotch.io/@nomanurrehman) Jan26,2017


Monthly Best
Tutorials(https://scotch.io/tutorials)
Comments(https://scotch.io/tutorials/working-with-json-in-mysql#disqus_thread)

12,461

RELATEDCOURSE

GET STARTED WITH JAVASCRIPT FOR WEB DEVELOPMENT


(https://hrd.cm/2k90ljr)
JavaScriptisthelanguageonfire.Buildanappforanyplatformyouwantincluding
website,server,mobile,anddesktop.

Get Started
)

(https://bit.ly/2koLun3)
ps
hi
ps

rs
hi

so
rs

on
so

sp
on

e/
Sp

yp
/t
.io
ch
ot
sc
//
s:
)
ps
hi
ps

rs
hi

so
rs

on
so

sp
on

e/
Sp

yp
SQLdatabasestendtoberigid.

/t
io
h.
tc
co
/s
:/
ps
tt
(h
Ifyouhaveworkedwiththem,youwouldagreethatdatabase
designthoughitseemseasier,isalottrickierinpractice.SQL
databasesbelieveinstructure,thatiswhyit'scalledstructured
querylanguage.

Ontheothersideofthehorizon,wehavetheNoSQLdatabases,
alsocalledschema-lessdatabasesthatencourageflexibility.In
schema-lessdatabases,thereisnoimposedstructuralrestriction,
Best Courses

onlydatatobesaved.

Thougheverytoolhasit'susecase,sometimesthingscallfora
hybridapproach.

Whatifyoucouldstructuresomepartsofyourdatabaseandleave
otherstobeflexible?

MySQLversion5.7.8
(https://dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-
8.html)introducesaJSONdatatypethatallowsyoutoaccomplish
that.

Inthistutorial,youaregoingtolearn.

1.HowtodesignyourdatabasetablesusingJSONfields.

2.ThevariousJSONbasedfunctionsavailableinMYSQLto ()
create,read,update,anddeleterows.

3.HowtoworkwithJSONfieldsusingtheEloquentORMin
Laravel.

# Why Use JSON


Atthismoment,youareprobablyaskingyourselfwhywouldyou
wanttouseJSONwhenMySQLhasbeencateringtoawidevariety
ofdatabaseneedsevenbeforeitintroducedaJSONdatatype.
(https://hrd.cm/2k90ljr)
Theanswerliesintheuse-caseswhereyouwouldprobablyusea
make-shiftapproach.

Letmeexplainwithanexample.
Supposeyouarebuildingawebapplicationwhereyouhavetosave
auser'sconfiguration/preferencesinthedatabase.

Generally,youcancreateaseparatedatabasetablewiththe id ,
user_id , key ,and value fieldsorsaveitasaformattedstringthat
youcanparseatruntime.

However,thisworkswellforasmallnumberofusers.Ifyouhave
aboutathousandusersandfiveconfigurationkeys,youare
lookingatatablewithfivethousandrecordsthataddressesavery
smallfeatureofyourapplication.

Orifyouaretakingtheformattedstringroute,extraneouscode
thatonlycompoundsyourserverload.

UsingaJSONdatatypefieldtosaveauser'sconfigurationinsucha
scenariocanspareyouadatabasetable'sspaceandbringdown
thenumberofrecords,whichwerebeingsavedseparately,tobe
thesameasthenumberofusers.

AndyougettheaddedbenefitofnothavingtowriteanyJSON
parsingcode,theORMorthelanguageruntimetakescareofit.

# The Schema
BeforewediveintousingallthecoolJSONstuffinMySQL,weare
goingtoneedasampledatabasetoplaywith.

So,let'sgetourdatabaseschemaoutofthewayfirst.

Wearegoingtoconsidertheusecaseofanonlinestorethat
housesmultiplebrandsandavarietyofelectronics.

Sincedifferentelectronicshavedifferentattributes(comparea
MacbookwithaVacuumnCleaner)thatbuyersareinterestedin, (https://hrd.cm/2k90ljr)
HIRED
typicallytheEntityattributevaluemodel(EAV)
(https://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%93value_model)
(https://hrd.cm/2k90ljr) Hired is the absolute best way to nd a tech or

design job.
patternisused.
(https://twitter.com/intent/tweet?url=https%3A%2F%2Fscotch.io%2Ftutorials%2Fworking-with-json-in- Get Hired.

mysql&text=Working+with+JSON+in+MySQL&via=scotch_io&related=scotch_io)
However,sincewenowhavetheoptiontouseaJSONdatatype,we
Subscribe & get our FREE eBook

aregoingtodropEAV.
Build Your First Node.js App
Forastart,ourdatabasewillbenamed e_store andhasthree

Email Address
tablesonlynamed, brands , categories ,and products respectively.

Free Node Book

Our brands and categories tableswillbeprettysimilar,eachhaving


an id anda name field.

SQL

CREATE DATABASE IF NOT EXISTS `e_store`


DEFAULT CHARACTER SET utf8
DEFAULT COLLATE utf8_general_ci;

SET default_storage_engine = INNODB;

CREATE TABLE `e_store`.`brands`(


`id` INT UNSIGNED NOT NULL auto_increment ,
`name` VARCHAR(250) NOT NULL ,
PRIMARY KEY(`id`)
);

CREATE TABLE `e_store`.`categories`(


`id` INT UNSIGNED NOT NULL auto_increment ,
`name` VARCHAR(250) NOT NULL ,
PRIMARY KEY(`id`)
);

Theobjectiveofthesetwotableswillbetohousetheproduct
categoriesandthebrandsthatprovidetheseproducts.

Whileweareatit,letusgoaheadandseedsomedataintothese
tablestouselater.
FIND YOUR
OPPORTUNITY

HIRED

(https://hrd.cm/2k90ljr)
SQL

/* Brands */
INSERT INTO `e_store`.`brands`(`name`)
VALUES
('Samsung');

INSERT INTO `e_store`.`brands`(`name`)


VALUES
('Nokia');

INSERT INTO `e_store`.`brands`(`name`)


VALUES
('Canon');

/* Types of electronic device */


INSERT INTO `e_store`.`categories`(`name`)
VALUES
('Television');

INSERT INTO `e_store`.`categories`(`name`)


VALUES
('Mobilephone');

INSERT INTO `e_store`.`categories`(`name`)


VALUES
('Camera');

Next,isthebusinessareaofthistutorial.

Wearegoingtocreatea products tablewiththe id , name , brand_id ,


category_id ,and attributes fields.

(https://hrd.cm/2k90ljr)
SQL

CREATE TABLE `e_store`.`products`(


`id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(250) NOT NULL ,
`brand_id` INT UNSIGNED NOT NULL ,
`category_id` INT UNSIGNED NOT NULL ,
`attributes` JSON NOT NULL ,
PRIMARY KEY(`id`) ,
INDEX `CATEGORY_ID`(`category_id` ASC) ,
INDEX `BRAND_ID`(`brand_id` ASC) ,
CONSTRAINT `brand_id` FOREIGN KEY(`brand_id`) REFERENCES `e_store`.`brands
CONSTRAINT `category_id` FOREIGN KEY(`category_id`) REFERENCES `e_store
);

Ourtabledefinitionspecifiesforeignkeyconstraintsforthe
brand_id and category_id fields,specifyingthattheyreferencethe
brands and categories tablerespectively.Wehavealsospecifiedthat
thereferencedrowsshouldnotbeallowedtodeleteandif
updated,thechangesshouldreflectinthereferencesaswell.

The attributes field'scolumntypehasbeendeclaredtobeJSON


whichisthenativedatatypenowavailableinMySQL.Thisallowsus
tousethevariousJSONrelatedconstructsinMySQLonour
attributes field.

Hereisanentityrelationshipdiagramofourcreateddatabase.

(https://hrd.cm/2k90ljr)
Ourdatabasedesignisnotthebest
intermsofefficiencyandaccuracy.
Thereisnopricecolumninthe
products tableandwecoulddowith

puttingaproductintomultiple
categories.However,thepurposeof
thistutorialisnottoteachdatabase
designbutratherhowtomodel
objectsofdifferentnatureinasingle
tableusingMySQL'sJSONfeatures.

(https://hrd.cm/2k90ljr)
# The CRUD Operations
Letuslookathowtocreate,read,update,anddeletedataina
JSONfield.

CREATE
CreatingarecordinthedatabasewithaJSONfieldisprettysimple.

AllyouneedtodoisaddvalidJSONasthefieldvalueinyourinsert
statement.

(https://hrd.cm/2k90ljr)
SQL

/* Let's sell some televisions */


INSERT INTO `e_store`.`products`(
`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Prime' ,
'1' ,
'1' ,
'{"screen": "50 inch", "resolution": "2048 x 1152 pixels", "ports": {"hdmi": 1, "usb": 3}, "speakers": {"left": "
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Octoview' ,
'1' ,
'1' ,
'{"screen": "40 inch", "resolution": "1920 x 1080 pixels", "ports": {"hdmi": 1, "usb": 2}, "speakers": {"left": "
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Dreamer' ,
'1' ,
'1' ,
'{"screen": "30 inch", "resolution": "1600 x 900 pixles", "ports": {"hdmi": 1, "usb": 1}, "speakers": {"left": "1
);

(https://hrd.cm/2k90ljr)
INSERT INTO `e_store`.`products`(
`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Bravia' ,
'1' ,
'1' ,
'{"screen": "25 inch", "resolution": "1366 x 768 pixels", "ports": {"hdmi": 1, "usb": 0}, "speakers": {"left": "5
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Proton' ,
'1' ,
'1' ,
'{"screen": "20 inch", "resolution": "1280 x 720 pixels", "ports": {"hdmi": 0, "usb": 0}, "speakers": {"left": "5
);

InsteadoflayingouttheJSONobjectyourself,youcanalsousethe
built-in JSON_OBJECT function.

The JSON_OBJECT functionacceptsalistofkey/valuepairsintheform


JSON_OBJECT(key1, value1, key2, value2, ... key(n), value(n)) andreturnsa
JSONobject.

(https://hrd.cm/2k90ljr)
SQL

/* Let's sell some mobilephones */


INSERT INTO `e_store`.`products`(
`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Desire' ,
'2' ,
'2' ,
JSON_OBJECT(
"network" ,
JSON_ARRAY("GSM" , "CDMA" , "HSPA" , "EVDO") ,
"body" ,
"5.11 x 2.59 x 0.46 inches" ,
"weight" ,
"143 grams" ,
"sim" ,
"Micro-SIM" ,
"display" ,
"4.5 inches" ,
"resolution" ,
"720 x 1280 pixels" ,
"os" ,
"Android Jellybean v4.3"
)
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Passion' ,
'2' ,
'2' ,
JSON_OBJECT(
(https://hrd.cm/2k90ljr)
"network" ,
JSON_ARRAY("GSM" , "CDMA" , "HSPA") ,
"body" ,
"6.11 x 3.59 x 0.46 inches" ,
"weight" ,
"145 grams" ,
"sim" ,
"Micro-SIM" ,
"display" ,
"4.5 inches" ,
"resolution" ,
"720 x 1280 pixels" ,
"os" ,
"Android Jellybean v4.3"
)
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Emotion' ,
'2' ,
'2' ,
JSON_OBJECT(
"network" ,
JSON_ARRAY("GSM" , "CDMA" , "EVDO") ,
"body" ,
"5.50 x 2.50 x 0.50 inches" ,
"weight" ,
"125 grams" ,
"sim" ,
"Micro-SIM" ,
"display" ,
"5.00 inches" ,
"resolution" ,
"720 x 1280 pixels" ,
"os" ,
"Android KitKat v4.3"
)
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
(https://hrd.cm/2k90ljr)
`category_id` ,
`attributes`
)
VALUES(
'Sensation' ,
'2' ,
'2' ,
JSON_OBJECT(
"network" ,
JSON_ARRAY("GSM" , "HSPA" , "EVDO") ,
"body" ,
"4.00 x 2.00 x 0.75 inches" ,
"weight" ,
"150 grams" ,
"sim" ,
"Micro-SIM" ,
"display" ,
"3.5 inches" ,
"resolution" ,
"720 x 1280 pixels" ,
"os" ,
"Android Lollypop v4.3"
)
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Joy' ,
'2' ,
'2' ,
JSON_OBJECT(
"network" ,
JSON_ARRAY("CDMA" , "HSPA" , "EVDO") ,
"body" ,
"7.00 x 3.50 x 0.25 inches" ,
"weight" ,
"250 grams" ,
"sim" ,
"Micro-SIM" ,
"display" ,
"6.5 inches" ,
"resolution" ,
"1920 x 1080 pixels" ,
(https://hrd.cm/2k90ljr)
"os" ,
"Android Marshmallow v4.3"
)
);
Noticethe JSON_ARRAY functionwhichreturnsaJSONarraywhen
passedasetofvalues.

Ifyouspecifyasinglekeymultipletimes,onlythefirstkey/value
pairwillberetained.ThisiscallednormalizingtheJSONinMySQL's
terms.Also,aspartofnormalization,theobjectkeysaresortedand
theextrawhite-spacebetweenkey/valuepairsisremoved.

AnotherfunctionthatwecanusetocreateJSONobjectsisthe
JSON_MERGE function.

The JSON_MERGE functiontakesmultipleJSONobjectsandproducesa


single,aggregateobject.

(https://hrd.cm/2k90ljr)
SQL

/* Let's sell some cameras */


INSERT INTO `e_store`.`products`(
`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Explorer' ,
'3' ,
'3' ,
JSON_MERGE(
'{"sensor_type": "CMOS"}' ,
'{"processor": "Digic DV III"}' ,
'{"scanning_system": "progressive"}' ,
'{"mount_type": "PL"}' ,
'{"monitor_type": "LCD"}'
)
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Runner' ,
'3' ,
'3' ,
JSON_MERGE(
JSON_OBJECT("sensor_type" , "CMOS") ,
JSON_OBJECT("processor" , "Digic DV II") ,
JSON_OBJECT("scanning_system" , "progressive") ,
JSON_OBJECT("mount_type" , "PL") ,
JSON_OBJECT("monitor_type" , "LED")
)
);

INSERT INTO `e_store`.`products`(


(https://hrd.cm/2k90ljr)
`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Traveler' ,
'3' ,
'3' ,
JSON_MERGE(
JSON_OBJECT("sensor_type" , "CMOS") ,
'{"processor": "Digic DV II"}' ,
'{"scanning_system": "progressive"}' ,
'{"mount_type": "PL"}' ,
'{"monitor_type": "LCD"}'
)
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Walker' ,
'3' ,
'3' ,
JSON_MERGE(
'{"sensor_type": "CMOS"}' ,
'{"processor": "Digic DV I"}' ,
'{"scanning_system": "progressive"}' ,
'{"mount_type": "PL"}' ,
'{"monitor_type": "LED"}'
)
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Jumper' ,
'3' ,
'3' ,
JSON_MERGE(
(https://hrd.cm/2k90ljr)
'{"sensor_type": "CMOS"}' ,
'{"processor": "Digic DV I"}' ,
'{"scanning_system": "progressive"}' ,
'{"mount_type": "PL"}' ,
'{"monitor_type": "LCD"}'
)
);

Thereisalothappeningintheseinsertstatementsanditcangeta
bitconfusing.However,itisprettysimple.

Weareonlypassingobjectstothe JSON_MERGE function.Someof


themhavebeenconstructedusingthe JSON_OBJECT functionwesaw
previouslywhereasothershavebeenpassedasvalidJSONstrings.

Incaseofthe JSON_MERGE function,ifakeyisrepeatedmultiple


times,it'svalueisretainedasanarrayintheoutput.

AproofofconceptisinorderIsuppose.

SQL

/* output: {"network": ["GSM", "CDMA", "HSPA", "EVDO"]} */


SELECT JSON_MERGE(
'{"network": "GSM"}' ,
'{"network": "CDMA"}' ,
'{"network": "HSPA"}' ,
'{"network": "EVDO"}'
);

Wecanconfirmallourquerieswererunsuccessfullyusingthe
JSON_TYPE functionwhichgivesusthefieldvaluetype.

(https://hrd.cm/2k90ljr)
SQL

/* output: OBJECT */
SELECT JSON_TYPE(attributes) FROM `e_store`.`products`;

READ
Right,wehaveafewproductsinourdatabasetoworkwith.

FortypicalMySQLvaluesthatarenotoftypeJSON,awhereclause
isprettystraight-forward.Justspecifythecolumn,anoperator,and
thevaluesyouneedtoworkwith.

Heuristically,whenworkingwithJSONcolumns,thisdoesnotwork.

SQL

/* It's not that simple */


SELECT
*
FROM
`e_store`.`products`
WHERE
attributes = '{"ports": {"usb": 3, "hdmi": 1}, "screen": "50 inch", "speakers": {"left": "10 watt", "right": "10

WhenyouwishtonarrowdownrowsusingaJSONfield,youshould
befamiliarwiththeconceptofapathexpression.
(https://hrd.cm/2k90ljr)
Themostsimplestdefinitionofapathexpression(thinkJQuery
selectors)isit'susedtospecifywhichpartsoftheJSONdocument
toworkwith.
Thesecondpieceofthepuzzleisthe JSON_EXTRACT functionwhich
acceptsapathexpressiontonavigatethroughJSON.

Letussayweareinterestedintherangeoftelevisionsthathave
atleastasingleUSBandHDMIport.

SQL

SELECT
*
FROM
`e_store`.`products`
WHERE
`category_id` = 1
AND JSON_EXTRACT(`attributes` , '$.ports.usb') > 0
AND JSON_EXTRACT(`attributes` , '$.ports.hdmi') > 0;

Thefirstargumenttothe JSON_EXTRACT functionistheJSONtoapply


thepathexpressiontowhichisthe attributes column.The $

symboltokenizestheobjecttoworkwith.The $.ports.usb and


$.ports.hdmi pathexpressionstranslateto"taketheusbkeyunder
ports"and"takethehdmikeyunderports"respectively.

Oncewehaveextractedthekeysweareinterestedin,itispretty
simpletousetheMySQLoperatorssuchas > onthem.

Also,the JSON_EXTRACT functionhasthealias -> thatyoucanuseto


makeyourqueriesmorereadable.

Revisingourpreviousquery.

(https://hrd.cm/2k90ljr)
SQL

SELECT
*
FROM
`e_store`.`products`
WHERE
`category_id` = 1
AND `attributes` -> '$.ports.usb' > 0
AND `attributes` -> '$.ports.hdmi' > 0;

UPDATE
InordertoupdateJSONvalues,wearegoingtousethe JSON_INSERT ,
JSON_REPLACE ,and JSON_SET functions.Thesefunctionsalsorequirea
pathexpressiontospecifywhichpartsoftheJSONobjectto
modify.

TheoutputofthesefunctionsisavalidJSONobjectwiththe
changesapplied.

Letusmodifyallmobilephonestohaveachipsetpropertyaswell.

SQL

UPDATE `e_store`.`products`
SET `attributes` = JSON_INSERT(
`attributes` ,
'$.chipset' ,
'Qualcomm'
)
WHERE
`category_id` = 2;

(https://hrd.cm/2k90ljr)
The $.chipset pathexpressionidentifiesthepositionofthe chipset

propertytobeattherootoftheobject.

Letusupdatethe chipset propertytobemoredescriptiveusingthe


JSON_REPLACE function.

SQL

UPDATE `e_store`.`products`
SET `attributes` = JSON_REPLACE(
`attributes` ,
'$.chipset' ,
'Qualcomm Snapdragon'
)
WHERE
`category_id` = 2;

Easypeasy!

Lastly,wehavethe JSON_SET functionwhichwewillusetospecify


ourtelevisionsareprettycolorful.

SQL

UPDATE `e_store`.`products`
SET `attributes` = JSON_SET(
`attributes` ,
'$.body_color' ,
'red'
)
WHERE
`category_id` = 1;

(https://hrd.cm/2k90ljr)
Allofthesefunctionsseemidenticalbutthereisadifferenceinthe
waytheybehave.

The JSON_INSERT functionwillonlyaddthepropertytotheobjectifit


doesnotexistsalready.

The JSON_REPLACE functionsubstitutesthepropertyonlyifitisfound.

The JSON_SET functionwilladdthepropertyifitisnotfoundelse


replaceit.

DELETE
Therearetwopartstodeletingthatwewilllookat.

Thefirstistodeleteacertainkey/valuefromyourJSONcolumns
whereasthesecondistodeleterowsusingaJSONcolumn.

Letussaywearenolongerprovidingthe mount_type informationfor


camerasandwishtoremoveitforallcameras.

Wewilldoitusingthe JSON_REMOVE functionwhichreturnsthe


updatedJSONafterremovingthespecifiedkeybasedonthepath
expression.

SQL

UPDATE `e_store`.`products`
SET `attributes` = JSON_REMOVE(`attributes` , '$.mount_type')
WHERE
`category_id` = 3;

Forthesecondcase,wealsodonotprovidemobilephones
(https://hrd.cm/2k90ljr)
anymorethathavetheJellybeanversionoftheAndroidOS.
SQL

DELETE FROM `e_store`.`products`


WHERE `category_id` = 2
AND JSON_EXTRACT(`attributes` , '$.os') LIKE '%Jellybean%';

Asstatedpreviously,workingwithaspecificattributerequiresthe
useofthe JSON_EXTRACT functionsoinordertoapplythe LIKE

operator,wehavefirstextractedthe os propertyof
mobilephones(withthehelpof category_id )anddeletedallrecords
thatcontainthestring Jellybean .

# A Primer for Web Applications


Theolddaysofdirectlyworkingwithadatabasearewaybehindus.

Thesedays,frameworksinsulatedevelopersfromlower-level
operationsanditalmostfeelsalienforaframeworkfanaticnotto
beabletotranslatehis/herdatabaseknowledgeintoanobject
relationalmapper.

Forthepurposeofnotleavingsuchdevelopersheartbrokenand
wonderingabouttheirexistenceandpurposeintheuniverse,we
aregoingtolookathowtogoaboutthebusinessofJSONcolumns
intheLaravelframework.

(https://hrd.cm/2k90ljr)
Wewillonlybefocusingontheparts
thatoverlapwithoursubjectmatter
whichdealswithJSONcolumns.An
in-depthtutorialontheLaravel
frameworkisbeyondthescopeof
thispiece.

# Creating the Migrations


MakesuretoconfigureyourLaravelapplicationtouseaMySQL
database.

Wearegoingtocreatethreemigrationsfor brands , categories ,and


products respectively.

BASH

$ php artisan make:migration create_brands


$ php artisan make:migration create_categories
$ php artisan make:migration create_products

The create_brands and create_categories migrationsareprettysimilar


andandaregulationforLaraveldevelopers.

(https://hrd.cm/2k90ljr)
PHP

/* database/migrations/create_brands.php */

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateBrands extends Migration


{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('brands', function(Blueprint $table){
$table->engine = 'InnoDB';
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('brands');
}
}

/* database/migrations/create_categories.php */

<?php

(https://hrd.cm/2k90ljr)
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCategories extends Migration


{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('categories', function(Blueprint $table){
$table->engine = 'InnoDB';
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('categories');
}
}

The create_products migrationwillalsohavethedirectivesfor


indexesandforeignkeys.

(https://hrd.cm/2k90ljr)
PHP

/* database/migrations/create_products */

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateProducts extends Migration


{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('products', function(Blueprint $table){
$table->engine = 'InnoDB';
$table->increments('id');
$table->string('name');
$table->unsignedInteger('brand_id');
$table->unsignedInteger('category_id');
$table->json('attributes');
$table->timestamps();
// foreign key constraints
$table->foreign('brand_id')->references('id')->on('brands')->
$table->foreign('category_id')->references('id')->on('categories'
// indexes
$table->index('brand_id');
$table->index('category_id');
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
(https://hrd.cm/2k90ljr)
{
Schema::drop('products');
}
}
Payattentiontothe $table->json('attributes'); statementinthe
migration.

Justlikecreatinganyothertablefieldusingtheappropriatedata
typenamedmethod,wehavecreatedaJSONcolumnusingthe
json methodwiththename attributes .

Also,thisonlyworksfordatabaseenginesthatsupporttheJSON
datatype.

Engines,suchasolderversionsofMySQLwillnotbeabletocarry
outthesemigrations.

# Creating the Models


Otherthanassociations,thereisnotmuchneededtosetupour
modelssolet'srunthroughthemquickly.

(https://hrd.cm/2k90ljr)
PHP

/* app/Brand.php */

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Brand extends Model


{
// A brand has many products
public function products(){
return $this->hasMany('Product')
}
}

/* app/Category.php */

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Category extends Model


{
// A category has many products
public function products(){
return $this->hasMany('Product')
}
}

/* app/Product.php */

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

(https://hrd.cm/2k90ljr)
class Product extends Model
{
// Cast attributes JSON to array
protected $casts = [
'attributes' => 'array'
];

// Each product has a brand


public function brand(){
return $this->belongsTo('Brand');
}

// Each product has a category


public function category(){
return $this->belongsTo('Category');
}
}

Again,our Product modelneedsaspecialmention.

The $casts arraywhichhasthekey attributes setto array makes


surewheneveraproductisfetchedfromthedatabase,it's
attributes JSONisconvertedtoanassociatedarray.

Wewillseelaterinthetutorialhowthisfacilitatesustoupdate
recordsfromourcontrolleractions.

# Resource Operations

CREATING A PRODUCT
Speakingoftheadminpanel,theparameterstocreateaproduct
maybecominginthroughdifferentroutessincewehaveanumber
ofproductcategories.Youmayalsohavedifferentviewstocreate,
edit,show,anddeleteaproduct.

Forexample,aformtoaddacamerarequiresdifferentinputfields
thanaformtoaddamobilephonesotheywarrantseparateviews.

(https://hrd.cm/2k90ljr)
Moreover,onceyouhavetheuserinputdata,youwillmost
probabalyrunitthrougharequestvalidator,separateforthe
camera,andthemobilephoneeach.

ThefinalstepwouldbetocreatetheproductthroughEloquent.
Wewillbefocusingonthecameraresourcefortherestofthis
tutorial.Otherproductscanbeaddressedusingthecodeproduced
inasimilarmanner.

Assumingwearesavingacameraandtheformfieldsarenamed
astherespectivecameraattributes,hereisthecontrolleraction.

PHP

// creates product in database


// using form fields
public function store(Request $request){
// create object and set properties
$camera = new \App\Product();
$camera->name = $request->name;
$camera->brand_id = $request->brand_id;
$camera->category_id = $request->category_id;
$camera->attributes = json_encode([
'processor' => $request->processor,
'sensor_type' => $request->sensor_type,
'monitor_type' => $request->monitor_type,
'scanning_system' => $request->scanning_system,
]);
// save to database
$camera->save();
// show the created camera
return view('product.camera.show', ['camera' => $camera]);
}

FETCHING PRODUCTS
Recallthe $casts arraywedeclaredearlierinthe Product model.It
willhelpusreadandeditaproductbytreatingattributesasan
associativearray.

(https://hrd.cm/2k90ljr)
PHP

// fetches a single product


// from database
public function show($id){
$camera = \App\Product::find($id);
return view('product.camera.show', ['camera' => $camera]);
}

Yourviewwouldusethe $camera variableinthefollowingmanner.

(https://hrd.cm/2k90ljr)
HTML

<table>
<tr>
<td>Name</td>
<td>{{ $camera->name }}</td>
</tr>
<tr>
<td>Brand ID</td>
<td>{{ $camera->brand_id }}</td>
</tr>
<tr>
<td>Category ID</td>
<td>{{ $camera->category_id }}</td>
</tr>
<tr>
<td>Processor</td>
<td>{{ $camera->attributes['processor'] }}</td>
</tr>
<tr>
<td>Sensor Type</td>
<td>{{ $camera->attributes['sensor_type'] }}</td>
</tr>
<tr>
<td>Monitor Type</td>
<td>{{ $camera->attributes['monitor_type'] }}</td>
</tr>
<tr>
<td>Scanning System</td>
<td>{{ $camera->attributes['scanning_system'] }}</td>
</tr>
</table>

EDITING A PRODUCT
Asshownintheprevioussection,youcaneasilyfetchaproduct
andpassittotheview,whichinthiscasewouldbetheeditview.

(https://hrd.cm/2k90ljr)
Youcanusetheproductvariabletopre-populateformfieldsonthe
editpage.
Updatingtheproductbasedontheuserinputwillbeprettysimilar
tothe store actionwesawearlier,onlythatinsteadofcreatinga
newproduct,youwillfetchitfirstfromthedatabasebefore
updatingit.

SEARCHING BASED ON JSON ATTRIBUTES


Thelastpieceofthepuzzlethatremainstodiscussisquerying
JSONcolumnsusingtheEloquentORM.

Ifyouhaveasearchpagethatallowscamerastobesearched
basedontheirspecificationsprovidedbytheuser,youcandoso
withthefollowingcode.

PHP

// searches cameras by user provided specifications


public function search(Request $request){
$cameras = \App\Product::where([
['attributes->processor', 'like', $request->processor],
['attributes->sensor_type', 'like', $request->sensor_type],
['attributes->monitor_type', 'like', $request->monitor_type],
['attributes->scanning_system', 'like', $request->scanning_system
])->get();
return view('product.camera.search', ['cameras' => $cameras]);
}

Theretrivedrecordswillnowbeavailabletothe product.camera.search

viewasa $cameras collection.

DELETING A PRODUCT
Usinganon-JSONcolumnattribute,youcandeleteproductsby
specifyingawhereclauseandthencallingthe delete method.

Forexample,incaseofanID.
(https://hrd.cm/2k90ljr)
PHP

\App\Product::where('id', $id)->delete();

ForJSONcolumns,specifyawhereclauseusingasingleormultiple
attributesandthencallthe delete method.

PHP

// deletes all cameras with the sensor_type attribute as CMOS


\App\Product::where('attributes->sensor_type', 'CMOS')->delete();
}

# Curtains
WehavebarelyscratchedthesurfacewhenitcomestousingJSON
columnsinMySQL.

Wheneveryouneedtosavedataaskey/valuepairsinaseparate
tableorworkwithflexibleattributesforanentity,youshould
considerusingaJSONdatatypefieldinsteadasitcanheavily
contributetocompressingyourdatabasedesign.

Ifyouareinterestedindivingdeeper,theMySQLdocumentation
(https://dev.mysql.com/doc/refman/5.7/en/json.html)isagreat
resourcetoexploreJSONconceptsfuther.

Ihopeyoufoundthistutorialinterestingandknowledgeable.Until
mynextpiece,happycoding!
(https://hrd.cm/2k90ljr)
laravel(https://scotch.io/tag/laravel) php(https://scotch.io/tag/php)

(https://pub.scotch.io/@nomanurrehman)

Noman Ur Rehman MyScotchPosts


(https://pub.scotch.io/@nomanurrehman)
Iamafullstack,freelancewebdeveloperwhospecializesinLaravel,
Rails,andAmazonWebServices.IloveRegularExpressionsand

discussingideas.
(https://pub.scotch.io/@nomanurrehman) (https://twitter.com/nomanurrehman)

(https://github.com/nomanurrehman)

Next Up

Laravel Random Keys with Keygen


Whendevelopingapplications,itisusuallycommontoseerandomnesscomeintoplay-and
asaresult,many...

(https://scotch.io/tutorials/laravel-random-keys-with-keygen)
API(https://scotch.io/tag/api) composer(https://scotch.io/tag/composer) laravel(https://scotch.io/tag/laravel) php
(https://pub.scotch.io/@gladchinda)
(https://scotch.io/tag/php) tokens(https://scotch.io/tag/tokens)

(https://hrd.cm/2k90ljr)

Quick Tip: Display Dates Relatively in Laravel


WehavepreviouslylookedattheCarbonpackagebyBrianNesbittaswellasallthe
functionality...
(https://scotch.io/tutorials/quick-tip-display-dates-relatively-in-laravel)
(https://pub.scotch.io/@johnkariuki)

(https://hrd.cm/2k90ljr)
23Comments Scotch
1 Login

Recommend 2 Share SortbyBest

Jointhediscussion

Matin2daysago
FirstIwanttothanksforyourgreatandfunctionalarticle,yousavedmytime!
second:isthereanywaytohaveconstraintsonJSONfielditems?
Reply Share

NomanUrRehman>Matin5hoursago
Youarewelcome!

Constraintsasinthedatatypesallowedforanattribute?

Forexample,attributeabcshouldonlyacceptintegervalueswhereas
attributexyzshouldonlyacceptstringvalues?
Reply Share

AlbertRaj13daysago
Excellentman,thereisasmallspellmistake,thoughitsminormistakebettertobe
removed.:)
CREATINGAPRODUCT>3rdparagraph>Moreoever
Reply Share

NomanUrRehman>AlbertRaj5daysago
Thanksalotforpointingthatoutandtheappreciation:)
Reply Share

IvanEliseoTinajeroDiaz14daysago
WooMan,youreallydeserveabeer.Thanksforsharethiswonderfultutorial.
Regards
Reply Share

NomanUrRehman>IvanEliseoTinajeroDiaz5daysago
Youarewelcome:)
Reply Share

RobKumaramonthago
Aren'ttheforeignkeyconstraintsinthecreate_productsmigrationsincorrect?
Shouldn'tdeleteberestrictedandupdatebecascade?
Reply Share

NomanUrRehman>RobKumar20daysago
Thanksforpointingitout.Fixed.
Reply Share

SoftPdfamonthago
WhenItriedtoruntheselinesonphpmyadmin

CREATETABLE`e_store`.`products`(
`id`INTUNSIGNEDNOTNULLAUTO_INCREMENT,
`name`VARCHAR(250)NOTNULL,
`brand_id`INTUNSIGNEDNOTNULL,
`category_id`INTUNSIGNEDNOTNULL,
`attributes`JSONNOTNULL,
PRIMARYKEY(`id`),
INDEX`CATEGORY_ID`(`category_id`ASC),
(https://hrd.cm/2k90ljr)
INDEX`BRAND_ID`(`brand_id`ASC),
CONSTRAINT`brand_id`FOREIGNKEY(`brand_id`)REFERENCES
`e_store`.`brands`(`id`)ONDELETERESTRICTONUPDATECASCADE,
CONSTRAINT`category_id`FOREIGNKEY(`category_id`)REFERENCES
`e_store`.`categories`(`id`)ONDELETERESTRICTONUPDATECASCADE
)

IsawthefollowingError>>
#1064YouhaveanerrorinyourSQLsyntaxcheckthemanualthatcorresponds
toyourMariaDBserverversionfortherightsyntaxtousenear'JSONNOTNULL,
PRIMARYKEY(`id`),
INDEX`CATEGORY_ID`(`category_id`'atline6
Reply Share

NomanUrRehman>SoftPdfamonthago
YouareusingMariaDBwhereasthistutorialiswrittenforMySQL.

IamnotsureifMariaDBsupportsJSONcolumns.
Reply Share

ShahrozeNawaz>NomanUrRehman18daysago
YesMariaDbhasjsonfunctionstousewithcolumnsseethe
completeguideherehttps://mariadb.com/kb/en/m...
Reply Share

NomanUrRehman>ShahrozeNawaz15daysago
YourlinkpointstothedocumentationofJSONfunctionsin
theknowledgebase.

However,IcouldnotfindtheJSONdatatypeinthelisted
datatypesintheknowledgebase.

https://mariadb.com/kb/en/m...

Canyoupointtoaknowledgebaselinkthatclearlymentions
thereisaJSONdatatype?
Reply Share

ZrelliMajdi2monthsago
behindthescenedoesmysqlstoreeachjsonkeyasnewvalueorrepeatedkeywil
bereferenced
Reply Share

NomanUrRehman>ZrelliMajdi2monthsago
Thedocumentationsays:

"Optimizedstorageformat.JSONdocumentsstoredinJSONcolumnsare
convertedtoaninternalformatthatpermitsquickreadaccesstodocument
elements.WhentheserverlatermustreadaJSONvaluestoredinthis
binaryformat,thevalueneednotbeparsedfromatextrepresentation.The
binaryformatisstructuredtoenabletheservertolookupsubobjectsor
nestedvaluesdirectlybykeyorarrayindexwithoutreadingallvalues
beforeoraftertheminthedocument."
Reply Share

MichaelBOUVY2monthsago
ThanksNomanforthisexcellentarticle!

IguessusingJSON_EXTRACTfunctioninaWHEREclausemeansthatevery
singlerowofthetablehastobeprocessedtocheckifitmatches,right?Istherea
waytodefineindexesonJSONpaths?
Reply Share

OlivierDASINI>MichaelBOUVY23daysago
Verygoodarticle,onlytheindexpartismissing:)
YoucanindexJSONcontentwithGeneratedColumns.
Youcanfindmoredetailsinthisblogpost:http://dasini.net/blog/2015...
Reply Share

NomanUrRehman>MichaelBOUVY2monthsago
(https://hrd.cm/2k90ljr)
AsfarasIknow,youcannotindexJSONcolumnsdirectlyinMySQL.

However,thereisaworkaround,sortofavirtualcolumn.

Moredetailscanbefoundathttps://dev.mysql.com/doc/r...
Reply Share

NandaKumar2monthsago
NandaKumar2monthsago
AppreciatedArticle.Wellwritten.
Reply Share

NomanUrRehman>NandaKumar2monthsago
Thanks:)
Reply Share

Feras2monthsago
Howicanupgrademysqlversiononxampp?
Reply Share

NomanUrRehman>Feras2monthsago
It'sabitlongandcomplicatedprocedure.

ThebestadviceIcangiveyouisjustupdateXAMPP.

LastIchecked,theydocyclewithPHP/Apache/MySQLreleases.
Reply Share

Test2monthsago
Verygoodarticle,thanks!
Reply Share

NomanUrRehman>Test2monthsago
Youarewelcome!
Reply Share

Subscribe d AddDisqustoyoursiteAddDisqusAdd Privacy

Subscribe to get our free eBook

BUILD YOUR FIRST NODE.JS APP

Subscribe to the Scotch Newsletter

Get the Free eBook

(https://hrd.cm/2k90ljr)

TheTeam(/about) ThePub(https://pub.scotch.io) OurStuff AboutUs(/about)


(https://digital.scotch.io) ScotchSchool(https://school.scotch.io)

You might also like