Notes - Data Stores - Firebasecsteach424.github.io/.../ds-firebase-guide.pdfFirebase - basic setup...
Transcript of Notes - Data Stores - Firebasecsteach424.github.io/.../ds-firebase-guide.pdfFirebase - basic setup...
Notes-DataStores-FirebaseDrNickHayward
AgeneralintroandoutlineforusingFirebasewithJavaScriptbasedclient-sideandmobileapps.
Contents
introwhatisFirebase?
authenticationcloudstoragereal-timedatabase
Firebase-basicsetupFirebase-createreal-timedatabaseFirebase-importJSONdataFirebase-permissionsaddFirebasetoJSbasedapp
addto index.html -initialusage
JSbasedapp-initialusageforwebandcross-platformdefineDBconnectionref() method
writedatawritedata-setalldatawritedata-setdataforaspecificlocation
PromiseswithFirebaseremovedata
removedata-specifylocationremovedata-alldataremovedata- set() withnull
Updatedataupdatedata-existingpropertiesupdatedata-addnewpropertiesupdatedata-removepropertiesupdatedata-multiplepropertiesatdifferentlocationsupdatedata-Promisechain
readdatareaddata-alldata,oncereaddata-singledata,oncereaddata-listenerforchanges-subscribe
listener-whynotuseaPromise?
readdata-listenerforchanges-unsubscribe
workingwitharraysJSONimport-JSarrayissuesFirebase push() methodworkwitharrays-Firebase snapshot methods
createarrayfromFirebasedata
addlistenersforFirebasevaluechangeslistenereventsfordatastoreupdateschild_removed eventchild_changed eventchild_added event
Intro
Atitsheart,FirebaseoffersahostedNoSQLdatabase.Particularlyusefultous,thisdatastoreisJSON-based,offeringquick,easydevelopmentfromwebvieworUIlogictodatastore.Itsyncsourapp'sdataacrossmultipleconnecteddevicesinamatterofmilliseconds,andisavailableforofflineusageaswell.
Ineffect,itprovidesanAPIforaccessingandqueryingtheseJSONdatastoresinreal-timeforallconnectedusers.
However,Firebaseasahostedoptionismorethanjustdatastoresandreal-timeAPIaccess.Ithasnowgrown,largelyoverthelastyearorso,toincludeadditionalfeaturesforanalytics,cloud-basedmessaging,appauthentication,filestorage,testoptionsforAndroid,notifications,adverts,andmuchmore...
Duetoitsscopeandoptions,Firebasehasbecomeanincreasinglypopularoptionforbothwebandmobileapps.
ManyofFirebase'spatternsandasyncquerystructureswillalsoworkwithotherdatastoreoptions.Usually,itwillonlytakefewchangeshereortheretoportyourcomponents.
WhatisFirebase?
So,whatisFirebase?
It'sahostedplatform,acquiredbyGoogle,whichprovidesvariousoptionsfordatastarage,dataaccess,andreal-timedatabasequerying.Forexample,weoftenconsidertheAuthentication,CloudStorage,andReal-timeDatabaseformanyJavaScriptbasedapps,bothwebandmobile,wenowbuild.
authentication
AuthenticationwithFirebaseprovidesvariousbackendservicesandSDKstohelpdevelopersmanageauthenticationforanapp.Thisservicesupportsmanydifferentproviders,includingFacebook,Google,Twitter&c.usingtheindustrystandardOAuth2.0andOpenIDConnectprotocols.
cloudstorage
CloudStorageiscustomarilyusedforuploading,storing,andthendownloadingfilesforappsandtheirusers.Italsofeaturesausefulsafetycheckifandwhenauser'sconnectionisbrokenorlost.Ineffect,itmonitorstheconnectionandprogresstohelpsavebandwidthandtime.FilesareusuallystoredinaGoogleCloudStoragebucket,whichmeansthattheyshouldbeaccessibleusingeitherFirebaseorGoogleCloud.So,wemaythenconsiderusingtheGoogleCloudplatformforimagefiltering,processing,orperhapsevenvideoencoding&c.SuchmodifiedfilesmaythenbecomeavailabletoFirebaseagain,andanyconnectedapps.
Forexample,Google'sCloudPlatform
real-timedatabase
TheReal-timeDatabaseoffersahostedNoSQLdatastorewiththeabilitytoquicklyandeasilysyncdata.Thisdatasynchronisationisactiveacrossmultipledevices,inreal-time,asandwhenthedataisupdatedintheclouddatabase.
Besidesthesebannerservices,Firebasealsooffersextrassuchasanalytics,advertisingservicessuchasadwords,crashreporting,notifications,andvarioustestingoptions.
AllofthesemaybemonitoredandmaintainedfromtheFirebaseconsolewitharegisteredaccount.
Firebase-basicsetup
WecanstartusingFirebasebycreatinganaccountwiththeserviceusingastandardGoogleaccount,
Firebase
AfterloggingintoFirebase,youmaytheneitherviewtheGetStartedmaterialorsimplynavigatetotheFirebaseconsole.ThisiswherewecanmonitorandsetconfigurationsforFirebase.
AttheConsolepage,wecanthengetstartedbycreatinganewproject.Simplyclickontheoptionto Addproject ,andenterthenameofthisnewproject,andselectaregion.
You'llthenberedirectedtotheconsoledashboardpageforthenewproject.Thisisprimarilywhereweaccessthevariousoptionsforeachproject,andgenerallycontrolandmaintainourproject'sstructureandsetup.
DocumentationfortheFirebaseReal-Timedatabaseisasfollows,
https://firebase.google.com/docs/reference/js/firebase.database
Firebase-createreal-timedatabase
WecannowsetupadatabasewithFirebaseforatestJavaScriptbasedapp,includingwebandcross-platformmobile.
StartbyselectingtheDatabaseoptionfromtheleftsidebarontheConsoleDashboard.It'savailableundertheDEVELOPoption.Then,simplyselectGetStartedforthereal-timedatabase.
Thiswillthenpresentanemptydatabasewithanappropriatenametomatchthecurrentproject.Thisnameis,asyoumightexpect,derivedfromtheprojectnameandID.
DatawillbestoredinausefulJSONformatinthereal-timedatabaseonFirebase,soitshouldbefamiliarformostdevelopers.WealsoseesimilarpatternswithotherNoSQLdatastoressuchasMongoDB.
Ingeneral,workingwithFirebaseissimple,andformostexamplesit'salsostraightforwardtouse.It'salsopossibletogetstartedquicklydirectfromtheFirebaseconsole,orsimplyimportsomeexistingJSONforyourproject'sdata.
Image-Firebase
createadatabase
Firebase-importJSONdata
So,wemightstartwithsomesimpledatatohelptestFirebasewithaJavaScriptbasedapp.Wecanimportthefollowingintoourtestdatabase,andthenquerythedata&c.fromtheapp.
{"egypt":{"code":"eg","ancient_sites":{"abu_simbel":{"title":"abusimbel","kingdom":"upper","location":"aswangovernorate","coords":{"lat":22.336823,"long":31.625532},"date":{"start":{"type":"bc","precision":"approximate","year":1264},"end":{"type":"bc","precision":"approximate","year":1244}}},"karnak":{"title":"karnak","kingdom":"upper","location":"luxorgovernorate","coords":{"lat":25.719595,"long":32.655807
},"date":{"start":{"type":"bc","precision":"approximate","year":2055},"end":{"type":"ad","precision":"approximate","year":100}}}}}}
InFirebase,thisJSONwillbestoredasfollows,
Image-Firebase
JSONimport
Firebase-permissions
Oneofthethingsyou'llnoticewhenyouinitiallycreateadatabasewithFirebaseisapersistentnotificationconcerningDefaultsecurityrulesrequireuserstobeauthenticated.WehavetheoptiontoeitherLEARNMOREorDISMISSthisnotification.
However,it'sworthconsidering,foramoment,howpermissionsaremanagedwithFirebase.
WecanmanagedatabaseaccessforourusersastheyloginandauthenticatewiththeFirebaseservice.Therearemanyoptionsavailableforpermissions,e.g.
Firebase-databaserules
butafewwemayconsidertogetusstarted.Forexample,ifweclicktheRULEStabwecanmodifyourrulestopermitaccesstothedatawithoutauthentication.Thiswill,ofcourse,helpusinitiallytestourapppriortoaddinganyrequiredauthentication.
So,wemodifytherulesasfollows.From,
{"rules":{".read":"auth!=null",".write":"auth!=null"}}
to
{"rules":{".read":"true",".write":"true"}}
AddFirebasetoJSbasedapp
WecannowtestournewFirebasedatabasewithaJavaScriptbasedapp.
WeneedtostartbygettingsomeusefulinformationfromFirebase,inparticularbyselectingtheoptionfromtheconsoletoAddtoapp.
SelecttheProjectOverviewlinkintheleftsidebar,andthenclickontheiconforAddapp.
ThiswillshowoptionsforAndroidandiOSnative,plusJavaScript.
We'renotlimitedtousingFirebasewithjustaJSbasedwebapp,butwecantakeadvantageoftheprovidedJavaScriptSDKwithotheroptionssuchasApacheCordova,ReactNative,andwebdevelopment&c.
TheFirebaseconsolewillshowusamodalwithinitialisationsettingsforaddingFirebaseusagetoourapp.
Forexample,we'llgetthefollowingsampleconfigforourtestdatabase.
Image-Firebase
initialisationconfigsettings
Wecanstartbycopyingtheseconfigvaluesforusewithourapp.
addto index.html -initialusage
We'llstartbytestingthissetupwiththedefaultconfiginour index.html file.
e.g.
<!--JS-Firebaseapp--><scriptsrc="https://www.gstatic.com/firebasejs/5.5.4/firebase.js"></script><script>//InitializeFirebasevarconfig={apiKey:"YOUR_API_KEY",authDomain:"422cards.firebaseapp.com",databaseURL:"https://422cards.firebaseio.com",projectId:"422cards",storageBucket:"422cards.appspot.com",messagingSenderId:"282356174766"};firebase.initializeApp(config);</script>
ThisexampleincludesinitialisationinformationsotheSDKhasaccessto
AuthenticationCloudstorageRealtimeDatabaseCloudFirestore
n.b.don'tforgettomodifytheabovevaluestomatchyourownaccountanddatabase...
However,it'salsopossibletocustomiserequiredcomponentsperapp.Thisallowsustoincludeonlythefeaturesrequiredforeachapp.Forexample,theonlyrequiredcomponentis
firebase-app -coreFirebaseclient(requiredcomponent)
<!--FirebaseAppisalwaysrequiredandmustbefirst--><scriptsrc="https://www.gstatic.com/firebasejs/5.5.4/firebase.js"></script>
Then,wemayaddamixofthefollowingoptionalcomponents,
firebase-auth -variousauthenticationoptionsfirebase-database -realtimedatabasefirebase-firestore -cloudFirestorefirebase-functions -cloudbasedfunctionforFirebasefirebase-storgae -cloudstoragefirebase-messaging -Firebasecloudmessaging
<!--Addadditionalservicesthatyouwanttouse--><scriptsrc="https://www.gstatic.com/firebasejs/5.5.3/firebase-auth.js"></script><scriptsrc="https://www.gstatic.com/firebasejs/5.5.3/firebase-database.js"></script><scriptsrc="https://www.gstatic.com/firebasejs/5.5.3/firebase-firestore.js"></script><scriptsrc="https://www.gstatic.com/firebasejs/5.5.3/firebase-messaging.js"></script><scriptsrc="https://www.gstatic.com/firebasejs/5.5.3/firebase-storage.js"></script>
<scriptsrc="https://www.gstatic.com/firebasejs/5.5.3/firebase-functions.js"></script>
Then,asnotedintheaboveinitialexample,wedefineanobjectforthe config oftherequiredservicesandoptions,
varconfig={//addAPIkey,services&c.};firebase.initializeApp(config);
JSbasedapp-initialusageforwebandcross-platform
Afterdefiningtherequiredconfigandinitialisation,wecanthenstarttoaddtherequiredlistenersandcallstoaJS-basedwebapporcross-platformmobileapp.
defineDBconnection
WecanestablishaconnectiontoourFirebaseDBasfollows,
constdb=firebase.database();
Wemaythenusethisreferencetoconnectandqueryourdatabase.
ref() method
Oncewehavetheconnectiontothedatabase,wemaythencallthe ref() ,orreference,method.
Weusethismethodtoread,write&c.datainthedatabase.
Bydefault,ifwecall ref() withnoarguments,ourquerywillberelativetotherootofthedatabase.Ineffect,we'llbereading,writing&c.relativetothewholedatabase.
Wemayalsorequestaspecificreferenceinthedatabasebypassingalocationpath,e.g.
db.ref('egypt/ancient_sites/abu_simbel/title').set('Abydos');
Thisexamplewillrequestareferencetothe title propertyinthespecifiedobjectrelativetothedatastoreroot.Wemaythenusethisreference,forexample,to set anewvalue.
Aswefindwithotherdatabases,suchastablesinSQLorcollectionsinMongoDB&c.,thisallowsustocreatemultiplepartsoftheFirebasedatabase.Suchpartsmightincludemultipleobjects,properties,andvalues&c.
Thisbecomesaquickandeasyoptionfororganisinganddistributingdatawithinthedatabase.
Writedata
Wemayalsowritedatatotheconnecteddatabase,againfromaJavaScriptbasedapplication.
FirebasesupportsmanydifferentJavaScriptdatatypes,including
stringsnumbersbooleansobjectsarrays...
Ineffect,anyvaluesanddatatypeswemaycustomarilyaddtoaJSONobject.However,it'sworthnotingthatFirebasemaynotmaintainthenativestructureuponimport.Arrays,forexample,willbeconvertedtoplainJavaScriptobjectsinFirebase.
writedata-setalldata
Wecan set dataforthewholedatabasebycallingthe ref() methodattheroot.
e.g.
db.ref().set({site:'abu-simbel',title:'AbuSimbel',date:'c.1264B.C.',visible:true,location:{country:'Egypt',code:'EG',address:'aswan'}coords:{lat:'22.336823',long:'31.625532'}});
So,thisexamplewillnowsetthedataforthewholedatabasetotheobjectpassedastheargumenttothe set()method.
However,thedatapasseddoesnothavetobeanobject.Wemaypassanyoftheabovesupporteddatatypes.
n.b.whenwecall set() relativetojusttheroot,theexistingdatawillbeoverwritten.Ineffect,thecurrentdatabaseisdeleted,andthepassedobjectbecomesthenewdatabase.
writedata-setdataforaspecificlocation
Aswithreadingspecificdata,wemayalsowritedatatoaspecificlocationinthedatabase.
Again,weaddanargumenttothe ref() methodspecifyingtherequiredlocationinthedatabase.
e.g.
db.ref('egypt/ancient_sites/abu_simbel/location').set('nearaswan');
ref() maybecalledrelativetoanydepthinthedatabasefromtheroot,therebyallowingustoupdateanythingfromthewholedatabasetoasinglepropertyvalue.
PromiseswithFirebase
FirebaseincludesnativesupportforPromisesandassociatedchains.
ThismeanswedonotneedtocreateourowncustomPromises.Instead,wemayworkwithareturnPromiseobjectfromFirebaseusingastandardchain.
Forexample,whenwecallthe set() method,FirebasewillreturnaPromiseobjectforthemethodexecution.
The set() methodwillnotexplicitlyreturnanythingexceptforsuccessorerror.Thismeanswecansimplycheckthereturnpromiseasfollows,
db.ref('egypt/ancient_sites/abu_simbel/title').set('AbuSimbel').then(()=>{//logdatasetsuccesstoconsoleconsole.log('dataset...');}).catch((e)=>{//catcgerrorfromFirebase-errorloggedtoconsoleconsole.log('errorreturned',e);});
Removedata
Asexpected,wherewecanaddnewdatatothedatabase,wemayalsodeleteandremovedatafromtheconnecteddatabase.
removedata-specifylocation
Aswithsettingdata,wemayalsodeletedataataspecificlocationintheconnecteddatabase.
e.g.
db.ref('egypt/ancient_sites/abu_simbel/kingdom').remove().then(()=>{//logdataremovedsuccesstoconsoleconsole.log('dataremoved...');}).catch((e)=>{//catcgerrorfromFirebase-errorloggedtoconsoleconsole.log('errorreturned',e);});
So,weneedtogetareferencetothespecificlocationinthedatabase,andthenexecutethe remove() methodforthatdata.Thiswilldeletethespecificpropertyanddatavalue.
Wemayalsochainastandard then() and catch() methodtothereturnPromiseobject.
removedata-alldata
Wemayalsoremoveallofthedataintheconnecteddatabase.
e.g.
db.ref().remove().then(()=>{//logdataremovedsuccesstoconsoleconsole.log('dataremoved...');}).catch((e)=>{//catcgerrorfromFirebase-errorloggedtoconsoleconsole.log('errorreturned',e);});
Aswecanseeinthisexample,wesimplyneedtocallthe ref() methodrelativetotherootoftheconnecteddatabase.Thiswilleffectivelywipeallofthecurrentdata.
removedata- set() withnull
AnotheroptionspecifiedintheFirebasedocsfordeletingdataisbyusingthe set() methodwitha null value.
e.g.
db.ref('egypt/ancient_sites/abu_simbel/kingdom').set(null).then(()=>{//logdataremovedsuccesstoconsoleconsole.log('datasettonull...');}).catch((e)=>{//catcgerrorfromFirebase-errorloggedtoconsoleconsole.log('errorreturned',e);});
(n.b.Whilstthisoptionworks,itseemsapooruseofthe set() method.Itisalsoapooruseofthe null datatype,whichisanobjecttypeinJavaScript.Thiscallis,therefore,reliantonFirebaseinterpretinga null valueanddatatypeasaremoverequesttothedatabase.)
Wemay,however,needtousethispatternwiththefollowing update() method.
Updatedata
Wemayalsocombinesettingandremovingdatainasinglepatternbyusingthe update() methodcalltothedefineddatabasereference.
The update() methodis,therefore,meanttobeusedtoupdatemultipleitemsinthedatabaseinasinglecall.Thismeanswemustpassanobjectastheargumenttothe update() method.
updatedata-existingproperties
So,ifwewantedtoupdatemultipleexistingpropertieswemighthavethefollowingexample,
db.ref('egypt/ancient_sites/abu_simbel/').update({title:'ThetempleofAbuSimbel',visible:false
});
updatedata-addnewproperties
Wemayalsoaddanewpropertyforthespecificlocationinthedatabase,
db.ref('egypt/ancient_sites/abu_simbel/').update({title:'ThetempleofAbuSimbel',visible:false,date:'c.1264B.C.'});
So,wemaynowsetnewvaluesforthetwoexistingproperties, title and visible ,andaddanewpropertyandvaluefor data .
Abenefitofthe update() methodisthatitwillonlyupdatethespecificproperties,andnotoverrideeverythingatthereferencelocationaswiththe set() method.
updatedata-removeproperties
Wemayalsocombinetheseupdateswiththeoptiontoremoveanexistingproperty,
e.g.
db.ref('egypt/ancient_sites/abu_simbel/').update({card:null,title:'ThetempleofAbuSimbel',visible:false,date:'c.1264B.C.',});
Aswithpassing null tothe set() method,we'reeffectivelydeletingthespecifiedpropertyfromthereferencelocationinthedatabase.
Therefore,we'renowabletocombinecreatinganewpropertywithupdatinganddeletinganyexistingpropertiesatthedefinedreferencelocation.
updatedata-multiplepropertiesatdifferentlocations
Wemayalsocombineupdatingdatainmultipleobjectsatdifferentlocationsrelativetotheinitialpassedreferencelocation.
e.g.
db.ref().update({'egypt/ancient_sites/abu_simbel/visible':true,'egypt/ancient_sites/karnak/visible':false});
Relativetotherootofthedabatase,we'venowupdatedmultiple title propertiesindifferentcards.
Thepropertyname,e.g. egypt/ancient_sites/abu_simbel/visible ,isinterpretedbyFirebaseasalocationinthedatabaserelativetothepassedrootreference.
n.b.thispatternofupdateisonlyrelativetothecurrentpathspecifiedintheargumentpassedtothe ref() method.Therefore,onlychildpropertiesofthecurrentlocationmaybeupdatedusingthispattern.Thisisduetocharacterrestrictionsonthepropertyname.e.g.thenamemaynotbeginwith . , / &c.
updatedata-Promisechain
The update() methodwillalsoreturnaPromiseobject,whichallowsustochainthestandardmethods.
e.g.
db.ref().update({'egypt/ancient_sites/abu_simbel/visible':true,'egypt/ancient_sites/karnak/visible':false}).then(()=>{console.log('updatesuccess...');}).catch((e)=>{console.log('error=',e);});
Aswith set() and remove() ,thePromiseobjectitselfwillsimplyreturnsuccessorerrorforthemethodcall.
Readdata
Wecanfetchdatafromtheconnecteddatabaseinmanydifferentways,includingallofthedataorasinglespecificpartofthedata.
Wemayalsoconnectandretrievedataonce,orsetupalistenerforpollingthedatabaseforliveupdates.
readdata-alldata,once
e.g.toretrievealldatafromthedatabaseasingletime,
//ALLDATAONCE-requestalldataONCE//-returnsPromisevaluedb.ref().once('value').then((snapshot)=>{//snapshotofthedata-requestthereturnvalueforthedataatthetimeofquery...constdata=snapshot.val();console.log('data=',data);}).catch((e)=>{console.log('errorreturned-',e);});
So,wecannowreturnallofthedatastoredinthedatabaseatthetimeofthisquery.i.e.asnapshotofthecurrentstateofthedatabase.
readdata-singledata,once
Likewise,wemayquerythedatabaseonceforasinglespecificvalue.
e.g.
//SINGLEDATA-ONCEdb.ref('egypt/ancient_sites/abu_simbel/').once('value').then((snapshot)=>{//snapshotofthedata-requestthereturnvalueforthedataatthetimeofquery...constdata=snapshot.val();console.log('singledata=',data);}).catch((e)=>{console.log('errorreturned-',e);});
So,thiswillreturnthevalueforthecardatlocation egypt/ancient_sites/abu_simbel/ .
readdata-listenerforchanges-subscribe
Wemayalsosetuplistenersforchangestotheconnecteddatabase,whichwillthencontinuetopolltheDBforanysubsequentchanges.
e.g.
//LISTENER-pollDBfordatachanges//-anychangesinthedatadb.ref().on('value',(snapshot)=>{console.log('listenerupdate=',snapshot.val());});
Byusingthe on() method,we'reabletosetupalistenerthatpollstheDBforanychangesin value .Asbefore,wemaythengetthecurrentsnapshotvalueforthedatastored.
Ifwechangeanydataintheonlinedatabase,thislistenerwillautomaticallyexecutethedefinedsuccesscallbackfunction.
Wemayalsoaddsomeinitialerrorhandlingforthesubscriptioncallback,e.g.
//LISTENER-SUBSCRIBE//-pollDBfordatachanges//-anychangesinthedatadb.ref().on('value',(snapshot)=>{console.log('listenerupdate=',snapshot.val());},(e)=>{console.log('errorreadingdb',e);});
listener-whynotuseaPromise?
Asthelistenerisnotifiedofupdatestotheonlinedatabase,weneedthecallbackfunctiontobeexecuted.Infact,wemayneedittobeexecutedmultipletimesformanyupdatestothestoreddata.
However,aPromisemayonlyberesolvedasingletimewitheither resolve or reject .So,ineffect,wewouldneedtoinstantiateanewPromiseforeachupdate.Thiswouldnotworkasexpected,whichiswhyweuseastandardcallbackfunction.
ThecallbackmaysimplybeexecutedeachandeverytimethereisanupdatetotheDB.
readdata-listenerforchanges-unsubscribe
Wemayalsoneedtounsubscribefromallorspecificchangesintheonlinedatabase.Forexample,ausermaynavigatetoadifferentscreenortheapplicationispausedinthebackground.
e.g.
db.ref().off();
ThiswillremoveallcurrentsubscriptionstothedefinedDBconnection.
However,wemayalsounsubscribeaspecificsubscriptionbysimplypassingthecallbackweusedfortheoriginalsubscription.
So,wemayabstractthecallbackfunctionandpassittoboththe on() and off() methodsforthedatabaseref() method.
e.g.
//abstractcallbackconstvalChange=(snapshot)=>{console.log('listenerupdate=',snapshot.val());};
Wemaythensimplypassthisvariableasthecallbackargumentforbothsubscribeandunsubscribeevents.
e.g.
//subscribedb.ref().on('value',valChange);//unsubscribedb.ref().off(valChange);
ThiswillallowourapptomaintaintheDBconnection,andunsubscribeaspecificsubscription.
workingwitharrays
Firebasedoesnotexplicitlysupportarraydatastructures.Instead,itwillconvertarrayobjectstoplainJavaScriptobjects.Thiswillnegatethebuilt-initeratorforanarrayobject,therebydefiningplainobjectsinthestoredJSONdata.
JSONimport-JSarrayissues
Forexample,ifweimportthefollowingJSON
{"cards":[{"visible":true,"title":"AbuSimbel","card":"templecomplexbuiltbyRamessesII"},{"visible":false,"title":"Amarna","card":"capitalcitybuiltbyAkhenaten"},{"visible":false,"title":"Giza","card":"Khufu'spyramidontheGizaplateauoutsideCairo"},{"visible":false,"title":"Philae","card":"templecomplexbuiltduringthePtolemaicperiod"}]}
InFirebase,thisJSONwillbestoredasfollows,
Image-Firebase
JSONimport
Eachindexvaluewillnowbestoredasaplainobjectwithanauto-incrementvaluefortheproperty.
e.g.
cards:{0:{card:"templecomplexbuiltbyRamessesII",title:"AbuSimbel",visible:"true"}}
So,wemaystillaccesseachindexvaluefromtheoriginalarrayobjectbutwithouteasyaccesstopre-defined,knownuniquereferences.
Forexample,toaccessthetitlevalueofagivencard,wewouldneedtoknowitsauto-generatedpropertyvalueinFirebase.
db.ref('cards/0')
Thisreferencewillbethepathtotherequiredobject,andwemaythenaccessagivenpropertyontheobject.
So,evenifweaddauniquereferencepropertytoeachcardwemaynotuseitwithoutknowingthepropertyvalueassignedtothecardbyFirebase.
Firebase push() method
ToaddnewcontenttoanexistingFirebasedatastore,wemayusethe push() methodtoaddthisdata.
Asthedataisaddedtothedatabase,auniquepropertyvaluewillbeauto-generated.
e.g.
//pushnewdatatospecificreferenceindbdb.ref('egypt/ancient_sites/').push({"philae":{"kingdom":"upper","visible":false}});
ThisnewdatawillbeaddedtotheconnectedDB,butitwillbecreatedwithanauto-generatedIDfortheparentobject,e.g.
LPcdS31H_u9N0dIn27_
Thismaybeusefulfordynamiccontentthatispushedtoadatastore,e.g.
notes,tasks,calendardates&c.
Ineffect,wemayusethisauto-generateduniquereferencewhilstiteratingovertheexistingDBcontent.
So,asweiteratethroughthedatastoreandoutputthecontent,wemayaddareferencetotheauto-generatedIDforfuturereferenceandlookup.Thisreferencemaybestoredinalocaldatastructure,UIcomponentorelement,variablevalue,&c.
workwitharrays-Firebase snapshot methods
DatasnapshotmethodsinFirebasedocumentation.
Acommonlyusedmethodwith snapshot isthe val() method,whichwe'vealreadyusedmanytimesalready.
However,therearemanyadditionalmethodsspecifiedintheAPIdocumentationforDataSnapshot.
forEach() -iteratorforplainobjectsfromFirebase
createarrayfromFirebasedata
AswestoredataasplainobjectsinFirebase,weneedtoconsiderhowwemayworkwitharray-likestructuresfortechnologiesandpatternsthatrequirearraydatastructures,suchasRedux.
Ineffect,wemaygetthedatafromFirebase,andthenprepareitforuseasanarray.
Forexample,tohelpusworkwithFirebaseobjectdataandarrays,wemaycallthe forEach() methodonthereturnsnapshot .ThiswillprovidearequirediteratorfortheplainobjectsstoredinFirebase.
e.g.
//getrefindbonce//callforEach()onreturnsnapshot//pushvaluestolocalarray//uniqueidforeachDBparentobjectis`key`propertyonsnapshotdb.ref('egypt/ancient_sites').once('value').then((snapshot)=>{constsites=[];snapshot.forEach((siteSnapshot)=>{sites.push({id:siteSnapshot.key,...siteSnapshot.val()});});
console.log('sitesarray=',sites);});
So,we'reabletoiteratethroughthereturnsnapshotvaluefortheconnectedDB.WemaythenpushselectedvaluestoeithercustompropertiesorusetheexistingpropertiesintheDB.
Inthisexample,wesetaspecificIDvalueinthearray,andthenusethespreadoperatortosimplyaddtheexistingpropertiesandvaluesfromthedatabasetothelocalarraydatastructure.
Forexample,wemayreturnthefollowing
Image-Firebase
snapshot forEach() -creatingalocalarray
So,wenowhavealocalarrayfromtheFirebaseobjectdata,whichwemaythenusewithoptionssuchasRedux.
AddlistenersforFirebasevaluechanges
Aswemodifyobjects,properties,values&c.inFirebase,wemaysetlistenerstoreturnnotificationsforsuchupdates.
So,thereshouldbeanotificationforagivenupdaterelativetothedatastore.
e.g.wemayaddasinglelistenerforanyupdaterelativetothefulldatastore
//LISTENER-SUBSCRIBE-v.2//-getalldata&thenpushreturndatatolocalarray...db.ref('egypt').on('value',(snapshot)=>{constsites=[];snapshot.forEach((siteSnapshot)=>{sites.push({id:siteSnapshot.key,...siteSnapshot.val()});});console.log('sitesarrayafterupdate=',sites);});
Asnotedearlier,the on() methoddoesnotreturnaPromiseobjectsoweneedtodefineacallbackforthereturndata.
listenereventsfordatastoreupdates
FirebaseprovidesafewdifferenteventsrelativetosubscriptionsandFirebaseupdates.
Forthe on() method,wemayinitiallyconsultthefollowingdocumentation,
on() eventsinFirebasedocs=https://firebase.google.com/docs/reference/js/firebase.database.Reference#on
Then,wemaytestvariouslistenersfordatastoreupdates.
child_removed event
Wemayaddasubscriptionforeventupdatesasachildobjectisremovedfromthedatastore.
The child_removed eventmaybeaddedasfollows,
//-listenforchild_removedeventrelativetocurrentrefpathinDBdb.ref('egypt/ancient_sites/').on('child_removed',(snapshot)=>{console.log('childremoved=',snapshot.key,snapshot.val());});
child_changed event
Likewise,wemayalsolistenforthe child_changed eventrelativetothecurrentpathpassedto ref() .
e.g.
//-listenforchild_changedeventrelativetocurrentrefpathinDBdb.ref('egypt/ancient_sites/').on('child_changed',(snapshot)=>{console.log('childchanged=',snapshot.key,snapshot.val());});
child_added event
Anothercommoneventisaddinganewchildtothedatastore.Forexample,ausermaycreateandaddanewnoteorto-doitem.
e.g.
//-listenforchild_addedeventrelativetocurrentrefpathinDBdb.ref('egypt/ancient_sites/').on('child_added',(snapshot)=>{console.log('childadded=',snapshot.key,snapshot.val());});
References
Firebase-https://firebase.google.com/FirebaseJSGuide-https://firebase.google.com/docs/web/setupFirebaseJSReference-https://firebase.google.com/docs/reference/js/FirebaseJS on() events-https://firebase.google.com/docs/reference/js/firebase.database.Reference#on