MongoDB tutustumista

SQL-tietokantojen rinnalle on tullut viime vuosina erittäin voimakkaasti ns. NoSQL -tietokannat. Niissä on etuna mm. suorituskyky kovan volyymin tietojenkäsittelyssä, joustavuus tietorakenteen muuttuessa sekä suora tuki JSON formaatille. Toisaalta käytössä ei ole esim. viiteavaimia tai join-kyselyjä.

Tässä postauksessa ei aleta esittelemään NoSQL -tietokantojen periaatteita laajasti vaan tutustutaan yhteen NoSQL -tietokantaan käytännössä ottamalla käyttöön MongoDB -tietokanta ja kokeilemalla muutamia operaatioita. NoSQL-tietokantojen periaatteisiin voi tutustua esim. alla olevan linkin kautta:
https://www.mongodb.com/nosql-explained

MongoDB tietokannan hyvät manuaalit löytyvät osoitteesta https://docs.mongodb.com/manual/

MongoDB tietokannan perustaminen pilveen

Pilvikoodarin blogissa MongoDB tietokanta halutaan perustaa suoraan pilveen. Vaihtoehtona olisi tietysti asentaa tietokantamoottori omalle koneelle ja kokeilla sitä paikallisesti mutta silloin sitä ei olisi helppo käyttää pilveen toteutetusta sovelluksesta käsin.

Valitsemme MongoDB tietokantapalvelun tarjoajaksi mlab.com palvelun joka tarjoaa tarvittaessa järeitäkin MongoDB ratkaisuja mutta tarjoaa myös mahdollisuuden perustaa yhden ilmaisen MongoDB -tietokannan joka toimii pilvipalveluna. Ilmaisen tietokannan maksimikoko on 0,5 Gt.

Perustaminen lähtee osoitteeesta https://mlab.com/ josta valitaan hostausympäristö: AWS / Azure / Google. Valitsemme ympäristöksi Azuren, jolloin siirrytään osoitteeseen https://mlab.com/azure/. Siellä valitaan plan eli millaisella setupilla lähdetään perustamaan tietokantaa:

mlab_plan_selection

Valitsemme siis ilmaisen Sandbox -tyyppisen planin.

Seuraavaksi tullaan rekisteröitymislomakkeelle:

mlab_signup

Kun tunnnus  on luotu, näytetäänkin jo käyttäjän aloitussivu. Ensimmäiseksi pitää vahvistaa sähköpostiosoite ennen kuin pystyy tekemään mitään:

mlab_first_login_

Kun sähköposti on vahvistettu, aktivoituvat toiminnot ja pääsemme perustamaan uutta tietokantaa:

mlab_account_activated

Valitsemme Create new ja pääsemme perustamaan uutta tietokantaa:

mlab_create_dbValitsemme palveluntarjoajaksi Azuren, sijainniksi North Europe (Dublin), ilmaisen single-noden, sekä syötämme tietokannan nimen. Hintana näkyy nolla dollaria per kuukausi 🙂

Tietokanta on ajossa heti perustamisen jälkeen:

mlab_running

Klikkaamalla riviä päästään katsomaan tarkempia tietoja:

mlab_details

Näytöllä kehoitetaan luomaan tietokantaan käyttäjä joten luodaan yksi käyttäjä ja sille salasana.

Nyt tietokantaan voidaan ottaa yhteys käyttämällä sivulla näkyvää tietokanta-urlia.

NoSQL tietokannan kokeilua

Kokeilemme seuraavaksi perustettua tietokantaa muutamilla operaatioilla.

Tarvitsemme kokeiluun editoria, jolla voimme suorittaa komentoja tietokantaan. Asennamme siksi omalle koneelle MongoDB paketin osoitteesta https://www.mongodb.com/download-center.

Asennuksessa voidaan asentaa myös palvelin mutta tarvitsemme toistaiseksi vain clientin. Lisätietoja asennuksesta omalle koneelle täältä: https://docs.mongodb.com/manual/tutorial/install-mongodb-on-windows/

Asennuspaketista asennamme siis nyt vain client-osuuden:

mongodb_install_client

Kun client (mongo.exe) on asennettu, voidaan ottaa yhteys tietokantaan:

mongodb_mongo_connect

Tietoturvasyistä olen sensuroinut osan komentokehotteen tekstistä, mutta komentoriville annetaan esimerkiksi komento

mongo ds30470.mlab.com:30470/pilvikoodari -u admin -p adminpassu

Sitten päästään itse asiaan eli komentamaan tietokantaa.

Esimerkiksi täältä saa esimerkkiä, miten SQL lauseita vastaavat operaatiot tehdään MongoDB-tietokantaan: https://docs.mongodb.com/manual/reference/sql-comparison/

Kokoelmaa (collection, SQL:ssä vastine on taulu) ei tarvitse erikseen perustaa vaan ne perustuvat samalla kun ensimmäisen kerran insertoidaan. Kokeillaan insertoida yksi dokumentti:

db.kayttajat.insert( { nimi : "Esko Ensimmäinen", syntvuosi : 1975 } )

vastauksena saadaan:

WriteResult({ "nInserted" : 1 })

Tehdään haku:

> db.kayttajat.find()

{ "_id" : ObjectId("5792487349f592026400dbf4"), "username" : "Esko Ensimmäinen", "year" : 1975 }

Eli dokumentti palautui JSON muodossa. MongoDB generoi automaattisesti jokaiselle dokumentille id:n.

Tehdään vielä muutama kokeiluluontoinen komento.

Kokoelmien listaus:

> show collections
kayttajat
system.indexes

Kokoelman droppaus:

> db.kayttajat.drop()
true
> show collections
system.indexes

Lisätään kolme dokumenttia ja haetaan suurempi kuin -operaattorilla:

> db.kayttajat.insert( { nimi : "Esko Ensimmäinen", syntvuosi : 1975 } )
WriteResult({ "nInserted" : 1 })
> db.kayttajat.insert( { nimi : "Teppo Toinen", syntvuosi : 1980 } )
WriteResult({ "nInserted" : 1 })
> db.kayttajat.insert( { nimi : "Kalle Kolmas", syntvuosi : 1990 } )
WriteResult({ "nInserted" : 1 })
db.kayttajat.find( { syntvuosi : {$gt : 1985} })
{ "_id" : ObjectId("5792537d49f592026400dbfa"), "nimi" : "Kalle Kolmas", "syntvuosi" : 1990 }

Indeksin luonti:

> db.kayttajat.createIndex( { syntvuosi : 1 } )
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}

Lisätään kaikille dokumenteille kenttä ”varmistettu” ja asetetaan olemassa oleville dokumenteille arvoksi false:

> db.kayttajat.update( {}, { $set: { varmistettu : false } },  {multi : true}  )
WriteResult({ "nMatched" : 3, "nUpserted" : 0, "nModified" : 3 })

> db.kayttajat.find()
{ "_id" : ObjectId("5792535f49f592026400dbf8"), "nimi" : "Esko Ensimmäinen", "syntvuosi" : 1975, "varmistettu" : false }
{ "_id" : ObjectId("5792536a49f592026400dbf9"), "nimi" : "Teppo Toinen", "syntvuosi" : 1980, "varmistettu" : false }
{ "_id" : ObjectId("5792537d49f592026400dbfa"), "nimi" : "Kalle Kolmas", "syntvuosi" : 1990, "varmistettu" : false }

Poistetaan ”varmistettu” -niminen kenttä:

> db.kayttajat.update( {}, { $unset: { varmistettu : false } },  {multi : true}  )
WriteResult({ "nMatched" : 3, "nUpserted" : 0, "nModified" : 3 })

> db.kayttajat.find()
{ "_id" : ObjectId("5792535f49f592026400dbf8"), "nimi" : "Esko Ensimmäinen", "syntvuosi" : 1975 }
{ "_id" : ObjectId("5792536a49f592026400dbf9"), "nimi" : "Teppo Toinen", "syntvuosi" : 1980 }
{ "_id" : ObjectId("5792537d49f592026400dbfa"), "nimi" : "Kalle Kolmas", "syntvuosi" : 1990 }

Haetaan vain syntymävuosi-kenttä ja sortataan sillä:

> db.kayttajat.find( {} , { syntvuosi:1} ).sort( {syntvuosi : 1})
{ "_id" : ObjectId("5792535f49f592026400dbf8"), "syntvuosi" : 1975 }
{ "_id" : ObjectId("5792536a49f592026400dbf9"), "syntvuosi" : 1980 }
{ "_id" : ObjectId("5792537d49f592026400dbfa"), "syntvuosi" : 1990 }

> db.kayttajat.find( {} , { syntvuosi:1} ).sort( {syntvuosi : -1})
{ "_id" : ObjectId("5792537d49f592026400dbfa"), "syntvuosi" : 1990 }
{ "_id" : ObjectId("5792536a49f592026400dbf9"), "syntvuosi" : 1980 }
{ "_id" : ObjectId("5792535f49f592026400dbf8"), "syntvuosi" : 1975 }

Find haku regural expression ehdolla:

> db.kayttajat.find( {nimi : /eppo/})
{ "_id" : ObjectId("5792536a49f592026400dbf9"), "nimi" : "Teppo Toinen", "syntvuosi" : 1980 }

Poistetaan käyttäjät joiden syntvuosi > 1985:

> db.kayttajat.remove({syntvuosi : {$gt: 1985} })
WriteResult({ "nRemoved" : 1 })

> db.kayttajat.find()
{ "_id" : ObjectId("5792535f49f592026400dbf8"), "nimi" : "Esko Ensimmäinen", "syntvuosi" : 1975 }
{ "_id" : ObjectId("5792536a49f592026400dbf9"), "nimi" : "Teppo Toinen", "syntvuosi" : 1980 }

Node.js ja MongoDB

Tehdään vielä lopuksi simppeli Node-ohjelma, joka ottaa yhteyden MongoDB tietokantaan ja tulostaa kokoelman ”kayttajat” sisällön.

Aivan aluksi haetaan npm:llä mongodb:

C:\nodejs>npm install mongodb --save
mongodb@2.2.4 node_modules\mongodb
├── es6-promise@3.0.2
├── readable-stream@1.0.31 (isarray@0.0.1, inherits@2.0.1, string_decoder@0.10.31, core-util-is@1.0.2)
└── mongodb-core@2.0.6 (bson@0.5.2, require_optional@1.0.0)

Sitten koodataan simppeli ohjelma joka ottaa tietokantayhteyden ja listaa kokoelman ”kayttajat” sisällön:

var client = require('mongodb').MongoClient;

// Otetaan yhteys tietokantaan
// HUOM! TÄMÄ DB URL EI OLE KÄYTÖSSÄ!
client.connect("mongodb://admin:adminpasssu@ds30470.mlab.com:30470/pilvikoodari", function(err, db) {
    if(!err) {
        console.log("Connected.");

        // haetaan kaikki käyttäjät taulukkoon
        findUsers(db, function(users) {
            console.log("Fetched following users:");
            console.log(users);
            db.close();
        } )
        
    } else {
        // yhteys ei onnistunut
        console.log(err);
    }
});

var findUsers = function(db, callback) {

    var collection = db.collection('kayttajat');

    collection.find({}).toArray(function(err, users) {
        callback(users);
    });
}

Ajetaan ohjelma:

C:\nodejs\projects\mongodb_test>node connect_and_print_users.js
Connected.
Fetched following users:
[ { _id: 5792535f49f592026400dbf8,
    nimi: 'Esko Ensimmäinen',
    syntvuosi: 1975 },
  { _id: 5792536a49f592026400dbf9,
    nimi: 'Teppo Toinen',
    syntvuosi: 1980 } ]

C:\nodejs\projects\mongodb_test>

Tässä postauksessa perustimme pilveen MongoDB tietokannan, kokeilimme hieman MongoDB:n syntaksin käyttöä ja lopulta teimme simppelin Node-ohjelman joka otti tietokantaan yhteyden.

MongoDB:n tiimoilta voisi kirjoittaa muitakin postauksia mongoDB:n todellisesta käytöstä Noden kanssa. Saattaa olla että palaamme asiaan 🙂