WF7. Deploying MongoDB content

Last updated: 2016-07-01

This HowTo part of a series starting with Mean stack: Preparing workflow on Windows.

It consist of notes taken from Chapter 5 in “Getting Mean With Mongo, Express, Angular, and Node“ about using Git and Heroku.

WF is short for Workflow meaning a manual process in this context.

WF7. Deploying MongoDB content

The steps to be done in this post are

  • A. Create local DB and Content
  • B. Retrive a Webapp (clone)
  • C. Test Webapp locally
  • D. Setup DB in Heroku (git init and git remote)
  • E. Backup and restore local content to Heroku
  • F. Test local Webapp against Heroku DB
  • G. Publish (push) Webapp to Heroku and test Heroku Webapp

A. Create local DB and Content

A1. Start MongoDB server

  • Open a DOS shell
  • $ mongodata #call a script from CZ5 to start mongod using your preferred data
  • > (ctrl-c to stop server)

A2. Start MongoDB client

Before starting a client a server (see A1) must be running

  • Using Mongo CLI shell
    • Open a DOS shell
    • $ mongo #start mongo shell
    • > (ctrl-c) #to disconnect from server
  • Or using MogoChef
    • Start MongoChef
    • Ctrl-L #start Open IntelliShell

A3. Create a DB

From a mongo shell (see A2) do:

  • > show dbs #does the DB already exist?
  • > use Loc8r #create the new DB and switch to it. Notice: DB name is case sensitive.
    switched to db Loc8r

A4. Create Content

From a mongo shell (see A2) do:

  • > show collections #does table (collection) already exist?
  • #Create a table (collection) named locations containing two rows (documents).
    Notice: Coords data must have longitude before latitude, which is the opposite of what you will find all other places like on MyGeoPosition or WhatsMyLatLng.
    Ref: P.149
> db.locations.save(
 [
 {
 "name": "Glostrup Runden",
 "address": "Rørsangervej 7, 2600 Glostrup",
 "rating": 3,
 "facilities": [
 "Cola",
 "Vingummi",
 "Citronkage"
 ],
 "coords": [
 12.405130,
 55.674201
 ],
 "openingTimes": [
 {
 "days": "Monday - Friday",
 "opening": "7:00am",
 "closing": "7:00pm",
 "closed": false
 },
 {
 "days": "Saturday",
 "opening": "8:00am",
 "closing": "5:00pm",
 "closed": false
 },
 {
 "days": "Sunday",
 "closed": true
 }
 ]
 },
 {
 "name": "Tour de Hvidovre",
 "address": "Dryadevej 19, 2650 Hvidovre",
 "rating": 2,
 "facilities": [
 "Energidrik",
 "Lakrids",
 "Skumfiduser"
 ],
 "coords": [
 12.483965,
 55.620440
 ],
 "openingTimes": [
 {
 "days": "Saturday",
 "opening": "11:00am",
 "closing": "3:00pm",
 "closed": false
 },
 {
 "days": "Sunday",
 "closed": true
 }
 ]
 }
 ])

Out:

BulkWriteResult({
 "writeErrors" : [ ],
 "writeConcernErrors" : [ ],
 "nInserted" : 2,
 "nUpserted" : 0,
 "nMatched" : 0,
 "nModified" : 0,
 "nRemoved" : 0,
 "upserted" : [ ]
})
  • #Add ($push) a sub document (to collection named reviews) to the 1st location document.
    Notice: The subdocument is itself resposible for creating an id, but the for the parent document it is optional/automatic.
    Ref: P.151
> db.locations.update(
 {"name": "Glostrup Runden"},
 {"$push": {
 "reviews": {
 "author": "Peter Plys",
 "id": ObjectId(),
 "rating": 5,
 "timestamp": new Date("09 Jun, 2016"),
 "reviewText": "Dejlig tur i solskin"
 }
 }
 }
 )

Out:

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
  • > db.locations.find({“name”: “Glostrup Runden”}).pretty() # print the 1st document.
    Omit the {query} to print all.
    Omit pretty() to print minified.
  • > show collections #do we have a table now?
    locations

B. Retrive a Webapp (clone)

  • Re-do WF6 with the exception that you should git clone chapter-07 instead of chapter-03 from step B1 and the folder you download to should be called loc8r07.

C. Test Webapp locally

  • Open a DOS shell
  • $ npm start #webserver on :3000
  • Browse to http://localhost:3000 #
  • > (ctrl-c) #stop webserver, when done testing

D. Setup DB in Heroku (git init and git remote)

Ref: P.153
The DB is setup as a MongoDB-As-A-Service in the cloud using MongoLab. Heroku is using AWS.

You could also use other cloud providers (e.g. Azure, Google), that supports MongoLab and follow the mLab quickstart.

If you already setup a Heroku account in step C2 in WF6, then you can either use the https://elements.heroku.com/addons/mongolab or use Heroku Toolbelt via a shell:

  • Open a DOS shell
  • $ cd . # /LocalGit/loc8r07. You should be in root of your webapp
  • Do step C1 in WF6. #Initialize local Repo
  • Do step C3 in WF6. #Create heroku app and remote repo
  • If you setup mongoDB via Heroku:
    • $ heroku addons:create mongolab -a stormy-coast-27 #add DB to app
      Note: Even though there is a free Sandbox tier with 500MB, then you are required to enter your credit card info on https://dashboard.heroku.com/account/billing.
      So I abandoned that way.
    • If you did setup mongoDB this way you can open a web interface to the DB with:
      $ heroku addons:open mongolab #query your mongoDB
  • I tried also to setup mongoDB via Azure:
    • To avoid having to enter credit card info I tried to use an Azure account. mlab is located under Markeplace of type App Service in the Azure portal.
      It failed to provision with this info:
      provisioning of new deployments through the Azure Marketplace has been disabled in preparation for shutting down our integration with the Marketplace on June 22, 2016. However, all our Azure plans will continue to be available directly via https://mlab.com.
  • I finally setup mongoDB directly from mlab:
    • Setup an account at mlab and create a DB from https://mlab.com/create:
    • Cloud provider: Aws (could also choose Google or Azure)
    • Region: US East
    • Plan: Single-node
    • Standard Line: Sandbox – Free #here you didn’t have to enter credit card
    • DB name: loc8r #Upper case not allowed
To connect using the mongo shell:
mongo ds013500.mlab.com:13500/loc8r -u <dbuser> -p <dbpassword>
To connect using a driver via the standard MongoDB URI:
 mongodb://<dbuser>:<dbpassword>@ds013500.mlab.com:13500/loc8r
  • mlab continued:
    • Click on the DB ds013500/loc8r
    • Find Text “Click here to create a new one” # to create a DB user. You will need the dbuser in the connection string.
    • Return to https://mlab.com/databases/loc8r when you want to review your connection details.
  • $ heroku config:get MONGOLAB_URI #Is environment var set with the mongoDB connection string?
    • If not then set it:
      $ heroku config:set MONGOLAB_URI=mongodb://<dbuser>:<dbpassword>@ds013500.mlab.com:13500/loc8r #set connection string in Heroku
      Setting MONGOLAB_URI and restarting stormy-coast-20… done, v4
    • Verify with config:get (see above)
  • $ echo mongo ds013500.mlab.com:13500/loc8r -u <dbuser> -p <dbpassword> > mongolab.bat #create a handy cloud mongoDB logon file in your app folder
  • $ mongolab #Connect to your cloud mongoDB
  • > db.getUsers() #If you get answer, then you are connected
  • > (ctrl-c) #quit connection

E. Backup and restore local content to Heroku

Ref: P.154
The steps to be done are:

  • E1. Change index in localDB
  • E2. Create a backup folder
  • E3. Backup from local DB
  • E4. Restore to remote DB

As follows

  • E1: Change index.
    This step fixes the index error in mlab:
    “Failed: loc8r.locations: error creating indexes for loc8r.locations: createIndex error: exception: unsupported geo index version { 2dsphereIndexVersion : 2dsphereIndexVersion: 3 }, only support versions: [1,2]”

    • Open a DOS shell
    • $ mongo
    • > use Loc8r
    • > db.locations.getIndexes()
[
 {
 "v" : 1,
 "key" : {
 "_id" : 1
 },
 "name" : "_id_",
 "ns" : "Loc8r.locations"
 },
 {
 "v" : 1,
 "key" : {
 "coords" : "2dsphere"
 },
 "name" : "coords_2dsphere",
 "ns" : "Loc8r.locations",
 "background" : true,
 "safe" : null,
 "2dsphereIndexVersion" : 3
 }
]
  • E1 continued:
    • > db.locations.dropIndex(“coords_2dsphere”)
      { “nIndexesWas” : 2, “ok” : 1 }
    • > db.locations.createIndex({
      coords : “2dsphere”},{
      “2dsphereIndexVersion” : 1},{
      “ns” : “Loc8r.locations”},{
      background : true}
      )
      {
      “createdCollectionAutomatically” : false,
      “numIndexesBefore” : 1,
      “numIndexesAfter” : 2,
      “ok” : 1
      }
    • > db.locations.getIndexes()
[
 {
 "v" : 1,
 "key" : {
 "_id" : 1
 },
 "name" : "_id_",
 "ns" : "Loc8r.locations"
 },
 {
 "v" : 1,
 "key" : {
 "coords" : "2dsphere"
 },
 "name" : "coords_2dsphere",
 "ns" : "Loc8r.locations",
 "2dsphereIndexVersion" : 1
 }
]
  • E1 continued:
    • > (ctrl-c) #disconnect
  • E2: Create folder
    • $ cd . # /LocalGit/
    • $ md tmp #mkdir
    • $ cd tmp
    • $ md mongodump
    • $ cd mongodump
  • E3: Backup
    • $ mongodump -h localhost:27017 -d Loc8r -o . #Backup to pwd “.”
      2016-06-13T21:30:32.800+0200 writing Loc8r.locations to Loc8r\locations.bson
      2016-06-13T21:30:32.806+0200 done dumping Loc8r.locations (2 documents)
  • E4: Restore
    • $ cd Loc8r #folder created by backup
    • $ mongorestore -h ds013500.mlab.com:13500 -d loc8r -u <dbuser> -p <dbpassword> . #Restore from pwd “.”
      2016-06-13T22:34:38.009+0200 building a list of collections to restore from . dir
      2016-06-13T22:34:38.227+0200 reading metadata for loc8r.locations from
      2016-06-13T22:34:38.232+0200 restoring loc8r.locations from
      2016-06-13T22:34:38.402+0200 restoring indexes for collection loc8r.locations from metadata
      2016-06-13T22:34:38.530+0200 finished restoring loc8r.locations (2 documents)
      2016-06-13T22:34:38.534+0200 done
    • Browse to https://mlab.com/databases/loc8r/collections/locations#documents to view or edit the data.

F. Test local Webapp against Cloud DB

Ref: p.157

By default the app will use the local DB. To be able to change setting to use the cloud DB the app uses environment var NODE_ENV

To use local DB the environment var NODE_ENV should be removed:

  • Edit line 6 of app_server\controllers\locations.js (from/to):
  • Open a DOS shell
  • Create a script for using local DB:
    • $ echo set NODE_ENV=> uselocaldb.bat #clear var (to use local DB)
    • $ echo set MONGOLAB_URI=>> uselocaldb.bat #clear var
    • $ echo set API_SERVER=>> uselocaldb.bat #clear var
    • $ echo npm start>> uselocaldb.bat #start webserver on :3000
    • $ uselocaldb #use local DB
  • Create a script for using cloud DB:
    • $ echo set NODE_ENV=production> useclouddb.bat #set var (to use cloud DB)
    • $ echo set MONGOLAB_URI=mongodb://<dbuser>:<dbpassword>@ds013500.mlab.com:13500/loc8r>> useclouddb.bat #set var
    • $ echo set API_SERVER=http://localhost:3000>> useclouddb.bat #set var
    • $ echo npm start>> useclouddb.bat #start webserver on :3000
    • $ useclouddb #use cloud DB
  • Verify setup and test:

G. Publish (push) Webapp to Heroku and test Heroku Webapp

Ref: p.156

  • Set enviroment vars in Heroku
    • $ heroku config:set NODE_ENV=production
    • $ heroku config:get MONGOLAB_URI # MONGOLAB_URI was set in D.
    • $ heroku config:set API_SERVER=https://stormy-coast-27.herokuapp.com #read from https://dashboard.heroku.com/apps 
  • Checkin (commit) and publish (push) – same as WF6 D.
    • $ git add . # add content to repo
    • $ git commit -m “1st push” # checkin
    • $ git push heroku master # deploy content to Heroku and remote build
  • Browse to https://stormy-coast-27.herokuapp.com/
    • $ heroku open

The end.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: