Tutorial > Mongo


Nodum beschikt standaard over een koppeling met MongoDB, een snelle en eenvoudig te configureren, non-sequentiële database. MongoDB is zeer geschikt voor het opslaan, muteren, opvragen en doorzoeken van (structuurongebonden) JSON-objecten. Om Mongo te gebruiken doorloop je eerst de stappen die je vindt onder modules > database. Als je dat doorlopen hebt dan kan je een collection aanmaken. Dit is zoals de naam ook al doet vermoeden een verzameling van door jou ingeplaatste data.

img

In het voorbeeld hebben we twee collections geplaatst; documentatie en personen. Je kan in elk willekeurig bestand de database aanroepen en de data bewerken. Het commando dat je uit moet voeren is wel afhankelijk van de collection waarin je de aanpassingen wilt uitvoeren. In de module Database staat onder meer het 'alias' van je collectie. In onderstaand voorbeeld gebruiken we de collectie 'Documentatie' die als alias 'mongo.' heeft. 'Mongo.' is de alias voor iedere collection die in een project wordt gemaakt na het instellen van MongoDB. Ieder andere collectie krijgt als alias de naam van de collectie. Het voordeel voor het gebruik van de standaardcollectie in MongoDB is dat de console autosuggesties geeft bij het gebruik van het mongo-object binnen nodum, {{ mongo. }}.

Binnen het Mongo-object van nodum kunnen verschillende functies worden uitgevoerd. Alle functies kunnen zowel in {% %}- als in {{ }}-vorm worden uitgevoerd. Let er wel op dat het bij het gebruik van {{ }} verstandig is om de sanitizer |pre te gebruiken. Het Mongo-object geeft alle resultaten terug in array-vorm en worden zonder |pre niet weergegeven in de browser.

{{ mongo.find('dier', { '$exists' : true })|pre }}
Zal het volgende teruggeven:
Array
(
    [0] => stdClass Object
        (
            [_id] => 56eabd29acef115a1018ef62
            [dier] => Eenhoorn
        )
)

In de module Database van je project is het mogelijk om je collection in te kijken. Hier vind je een weergave van de ingevoerde data, kunnen records verwijderd worden of kan de hele collection gewist worden.

De standaardcollectie met alias 'mongo' kan nooit worden verwijderd.

Data opvragen/tonen

mongo.find(string key / array/object filter, string/array/object value, string sort, int take=100, int skip=0, bool bsonObj=true ) – mongo.get( ... )
Hiermee zoek je binnen de MongoDB naar gegevens, en het geeft je vervolgens je gevonden documents terug. Het filter kan een string zijn (1:1 match), of kan een object zijn volgens de MongoDB filter syntax, waarbij ook gefilterd kan worden op bijv. groter dan, kleiner dan, of "veld aanwezig". Enkele voorbeelden:

Filteren gaat efficiënter als er een index op velden is aangemaakt waarop regelmatig wordt gefilterd.

Code Toelichting
{{ mongo.find('voornaam', 'José') }} Zoek naar alle records waarbij het veld voornaam letterlijk 'José' is.
{{ mongo.find('age', { '$gt' : 30, '$lt' : 50 }) }} Zoek naar alle records waarbij het veld 'age' groter is dan 30 en kleiner is dan 50.
{{ mongo.find('dier', { '$exists' : true }) }} Zoek naar alle records waar het veld 'dier' gevuld is.
{{ mongo.find({ dier : { '$exists' : true } }) }} Zoeken op objectbasis, gebruik hierbij geen aanhalingstekens.
{{ mongo.get('voornaam', { '$exists' : true }, 'age|desc', 2, 2) }} Alle records waar 'voornaam' bestaat, aflopend gesorteerd op leeftijd (moet dus ook bestaan), neem er 2, sla er 2 over.
{{ mongo.find(
{ '$text': {
'$search' : 'werkt online',
'$language' : 'dutch',
'$caseSensitive' : false,
'$diacriticSensitive' : false
}}, { score: { '$meta': "textScore" } },
{ score: { '$meta': "textScore" } }) }}
Zoeken, in het Nederlands Dus: "de het een" negeren, en zoek == zoeken en zoeken == zoek, inclusief de score en sortering op de match score.
{{ mongo.find({ '$text': { '$search' : 'software -optimaliseer' } })|pre }} Zoeken op een text-index, wel op het woord software, niet op het woord optimaliseer. Indien language 'dutch' meegegeven wordt, zie bovenstaand voorbeeld, dan zou 'optimaliseren' ook werken.

Met de update van versie 2.1.0 is het mogelijk om een mongo.find zonder argumenten te doen. Dit kan je doen door {{ mongo.find() }} te gebruiken.

Zoeken over meerdere velden
Met de update van versie 2.1.0 is het nu ook mogelijk om met het 3e argument in een mongo.find() een sortering toe te passen. Dat is een string, met de veldnaam, een pipe en vervolgens ASC of DESC. Er kan nu een object met veldkeys opgegeven worden, zodat een reeks van meerdere sorteringen gebruikt kan worden.

mongo.search(string word)
Hiermee zoek je op records waar het opgegeven woord in voorkomt. Het woord is hoofdletter-ongevoelig, en tevens ongevoelig voor accenten e.d. 'José' wordt dus ook gevonden met 'jose'. Deze opdracht werkt enkel op velden met een text index (createTextIndex) en enkel per heel woord (geen wildcard).

{{ mongo.search('jose')|pre }}

mongo.match(string key, string valueRegExp, [string regexpFlag] )
Zoek op records waar een deel van een string in voorkomt, optioneel op te geven als reguliere expressie. Optioneel kan een Flag worden opgegeven om bijvoorbeeld Case Insensitive ('i') te zoeken:

{{ mongo.match('achternaam', '^Laa.+', 'i') }}

Het bovenstaande voorbeeld zoekt op alle records die beginnen met "laa" gevolgd door een of meer karakters, en hoofdletterongevoelig.

Dit is een zeer inefficiënte manier van zoeken als er veel data aanwezig is, gezien alle records stuk voor stuk beoordeeld moeten worden op een match.

mongo.distinct(string key )
Verkrijg alle unieke waarden uit een veld. Bijvoorbeeld alle al aanwezige voornamen;

{{ mongo.distinct('voornaam') }}

mongo.aggregate(object aggQuery)

Dit is een gevorderde actie om uit te voeren. Lees eerst de documentatie over dit onderwerp.

Voer een MongoDB Aggregate Query uit (max, group, sum, enz.).

{# Voorbeeld #}
{% set companies = mongoauth.aggregate([
    { '$group'   :  {
                        "_id"          : { "$toLower" : "$companyName"  },
                        "subscription" : { '$first'   : "$subscription" },
                        "companyName"  : { '$first'   : "$companyName"  },
                        "lastLogin"    : { '$max'     : "$lastLogin"    },
                        "count"        : { '$sum'     : 1               },
                        "company"      : { '$max'     : "$company"      }
                    }
    },
    { '$sort'    :  { "_id":1 } },
    { '$skip'    :  0},
    { '$limit'   :  99999},
    { '$project' :  {
                        "companyName":1,
                        "company":1,
                        "lastLogin":1,
                        "count":1,
                        "subscription":1
                    }
    }
]) %}

Data toevoegen

mongo.insert(object jsonDocument) – alias: .set( .. )
Voeg een JSON record toe. Het toegekende unieke _id wordt retour gegeven als alles is gelukt. Om bijvoorbeeld een voornaam, achternaam en een leeftijd toe te voegen aan de data gebruik je het volgende statement;

{{ mongo.set({ voornaam: "José", tussenvoegsel: "van", achternaam: "Laar", age: 30 }) }}

Een ander voorbeeld om bijvoorbeeld een tijdstamp toe te voegen aan de data;

{% do mongo.set({ voornaam: "José", _moment : { "$date" : (''|date('U')) } }) %}

mongo.insertMany(array [object {jsonDocument}, { ... } ] n* )
Voeg meerdere JSON records in 1x toe. Een object met resultaatgegevens en ID's wordt retour gegeven.

mongo.insertMany(
  [
    { voornaam: "Wietse", achternaam: "Wind", leeftijd: 28 },
    { voornaam: "José", achternaam: "Laar", tussenvoegsel: "van", leeftijd: 30 },
    { voornaam: "John", achternaam: "Doe", leeftijd: 50 }
  ]
)

Data updaten

mongo.update(string id, object data, [bool replaceDocument] [bool upsert] ) – mongo.update(object filter, ...)
Wijzig één of meerdere records. Deze parameters behoeven wat extra uitleg:

1e parameter: een string met een document _id (1 record bijwerken) of een object met een filter, dat voldoet aan dezelfde eisen als bij een mongo.find opdracht. Indien een _id wordt gebruikt wordt 1 enkel record bijgewerkt. Indien een filter-object wordt opgegeven, worden alle records bijgewerkt die voldoen aan het filter.

2e parameter: de nieuwe data waarmee de gefilterde records moet(en) worden bijgewerkt (JSON object)

3e parameter (optioneel, standaard: false): vervang het bestaande document (standaard: false, dus keys + values worden bijgeschreven in plaats van overschreven)

4e parameter (optioneel, standaard: true): indien het record o.b.v. _id of filter (1e parameter) niet bestaan, doe dan een insert (voeg toe)

{# 1 record bijwerken (inhoud bijschrijven (mergen)) #}
    {{ mongo.update("56a0a995b513f20528545519", { leeftijd : 50 }, false) }}

{# 1 record vervangen (inhoud overschrijven) #}
    {{ mongo.update("56a0a995b513f20528545519", { voornaam :"John", achternaam: "Doe", leeftijd: 50 }, true) }}

{# meerdere records bijwerken, iedereen zonder tussenvoegsel "geenTsVg: true" geven #}
    {{ mongo.update({ 'voornaam' : { '$exists' : true }, 'tussenvoegsel' : { '$exists' : false } }, { geenTsVg : true }) }}

Data verwijderen

mongo.delete(string id) – mongo.delete(object filter)
Verwijdert één of meerdere records op basis van een string met een document_id (1 record verwijderen) of een object met een filter, dat voldoet aan dezelfde eisen als bij een mongo.find-opdracht. Indien een _id wordt gebruikt wordt 1 enkel record verwijderd. Indien een filter-object wordt opgegeven, worden alle records verwijderd die voldoen aan het filter.

{{ mongo.delete('56a0a995b513f20528545519') }}

Index

Met indexes is het gemakkelijker voor MongoDB om records te doorzoeken. Indexes kunnen ook in de module Database worden aangemaakt, door op het tandwiel naast het betreffende veld te klikken en 'Maak (normale) index' of 'Maak Zoekindex' te selecteren. mongo.createIndex(string key )
Maak een index op een veld, zodat het veld sneller doorzocht kan worden.

{{ mongo.createIndex('leeftijd') }}

mongo.createTextIndex(string key )
Maak een text-index op een veld, zodat het snel op woorden doorzocht kan worden.

{{ mongo.createTextIndex('toelichting') }}

mongo.getIndexes()
Verkrijg een lijst met de aanwezige indexes (per type, per veld).

{{ mongo.getIndexes('leeftijd') }}
Datum/tijd

Wil je de tijd en datum opslaan in Mongo gebruik dan de onderstaande code.

{{ ''|date('U, d-m-Y H:i:s') }}

{{ ''|date('U, d-m-Y H:i:s', "CET") }}

{{ ''|date('U, d-m-Y H:i:s', "GMT") }}

{{ ''|date('U, d-m-Y H:i:s', "America/Los_Angeles") }}

{{ ''|date('U, d-m-Y H:i:s', 'Europe/Amsterdam') }}

{{ ''|date('U, d-m-Y H:i:s', 'GMT+2') }}

{{ mongo.update({ '_moment': { '$exists' : true } }, { _moment : { "$date" : (''|date('U')) } } )|pre }}

Met de update van 2.0.7 is |date('Y-m-d H:i:s') niet meer nodig, omdat nodum bij Mongo Find / Delete / update snapt dat een string omgezet moet worden. (incl. "now", "next monday", etc.)

{{ test.find({ '$and' : [
    { moment : { '$gt' : { '$date' : 'now' } } },
    { moment : { '$lt' : { '$date' : 'now + 1 year' } } }
] })|pre }}

$date-filters kunnen nu worden gebruikt in de:

  • Query van een find() / get()
  • Data van een set() / insert()

In een delete() en update() kan in de DATA ook met $date gewerkt worden.

{{ test.update ({ '$and' : [
    { moment : { '$gt' : { '$date' : 'mow - 3 years' } } },
    { moment : { '$lt' : { '$date' : 'now + 2 years' } } }
] }, { updated: true, addData: "Bla" })|pre }}
Extra informatie

De documentatie van MongoDB zelf is hier te vinden.

Voorbeelden worden gegeven in MongoDB-syntax; deze is niet gelijk aan de syntax die gebruikt wordt in nodum. Filters kunnen wel worden overgenomen. Houd er rekening mee dat de syntax van Twig wel gerespecteerd moet worden, dus keys uit de Mongo-documentatie zonder quotes moeten dus voorzien worden van quotes.

Een goed voorbeeld is het volgende:

{{ mongo.find('woonplaats', { '$exists' : true }) }}

Een verkeerd voorbeeld is het volgende:

{{ db.collection.find('woonplaats', { $exists : true }) }}