sql >> Database >  >> NoSQL >> MongoDB

Realtime chatten met Modulus en Node.js

In deze tutorial laat ik je zien hoe je een realtime chat-applicatie implementeert met Node.js, Socket.IO en MongoDB, en dan zullen we deze applicatie samen in Modulus implementeren.

Laat me u eerst het definitieve uiterlijk van de applicatie laten zien die we aan het einde van het artikel zullen hebben.

Node.js wordt de kern van de applicatie, met Express als de MVC, MongoDB voor de database en Socket.IO voor realtime communicatie. Als we klaar zijn, zullen we onze applicatie in Modulus implementeren. Het MongoDB-gedeelte bestaat eigenlijk binnen Modulus.

1. Scenario

  1. John wil onze applicatie gebruiken en opent deze in de browser.
  2. Op de eerste pagina selecteert hij een bijnaam die hij tijdens het chatten gebruikt en logt hij in om te chatten.
  3. In het tekstgebied schrijft hij iets en drukt op Enter.
  4. De tekst wordt verzonden naar een RESTful-service (Express) en deze tekst wordt naar MongoDB geschreven.
  5. Voordat u in MongoDB schrijft, wordt dezelfde tekst uitgezonden naar de gebruikers die momenteel zijn aangemeld bij de chat-app.

Zoals je kunt zien, is dit een heel eenvoudige app, maar hij dekt bijna alles voor een webapplicatie. Er is geen kanaalsysteem in deze applicatie, maar je kunt de broncode afsplitsen en de kanaalmodule implementeren om te oefenen.

2. Projectontwerp vanaf nul

Ik zal proberen eerst de kleine stukjes van het project uit te leggen en ze aan het einde te combineren. Ik zal van de achterkant naar de voorkant beginnen. Laten we dus beginnen met de domeinobjecten (MongoDB-modellen).

2.1. Model

Voor database-abstractie gebruiken we Mongoose. In dit project hebben we slechts één model genaamd Message . Dit berichtmodel bevat alleen text , createDate ,  en author . Er is geen model voor de auteur zoals User omdat we een gebruikersregistratie-/inlogsysteem niet volledig zullen implementeren. Er zal een eenvoudige pagina zijn die een bijnaam geeft en deze bijnaam wordt in een cookie opgeslagen. Dit wordt gebruikt in het Message model als tekst in de author veld. Hieronder ziet u een voorbeeld van een JSON-model:

{

    text: "Hi, is there any Full Stack Developer here?"

    author: "john_the_full_stack",

    createDate: "2015.05.15"

}

Om dit soort documenten te maken, kunt u een model implementeren met behulp van de onderstaande Mongoose-functies:

var mongoose = require('mongoose')



var Message = new mongoose.Schema({

    author: String,

    message: String,

    createDate: {

        type: Date,

        default: Date.now

    }

});



mongoose.model('Message', Message)

Importeer eenvoudig de Mongoose-module, definieer uw model met de velden en veldattributen in JSON-indeling en maak een model met de naam Message . Dit model wordt opgenomen in de pagina's die u wilt gebruiken.

Misschien heb je een vraag over waarom we het bericht in de database opslaan, terwijl we dit bericht al naar de gebruiker in hetzelfde kanaal uitzenden. Het is waar dat je chatberichten niet hoeft op te slaan, maar ik wilde alleen de database-integratielaag uitleggen. Hoe dan ook, we zullen dit model gebruiken in ons project binnen de controllers. Beheerders?

2.2. Controller

Zoals ik al eerder zei, zullen we Express gebruiken voor het MVC-gedeelte. En C   hier staat voor de Controller . Voor onze projecten zijn er slechts twee eindpunten voor berichten. Een daarvan is voor het laden van recente chatberichten en de tweede is voor het verwerken van verzonden chatberichten om op te slaan in de database en vervolgens uit te zenden naar het kanaal.

.....

app.get('/chat', function(req, res){

    res.sendFile(__dirname + '/index.html');

});



app.get('/login', function(req, res){

    res.sendFile(__dirname + '/login.html');

});



app.post('/messages', function(req, res, next) {

    var message = req.body.message;

    var author = req.body.author;

    var messageModel = new Message();

    messageModel.author = author;

    messageModel.message = message;

    messageModel.save(function (err, result) {

       if (!err) {

           Message.find({}).sort('-createDate').limit(5).exec(function(err, messages) {

               io.emit("message", messages);

           });

           res.send("Message Sent!");

       } else {

           res.send("Technical error occurred!");

       }

    });

});



app.get('/messages', function(req, res, next) {

    Message.find({}).sort('-createDate').limit(5).exec(function(err, messages) {

        res.json(messages);

    });

});

.....

De eerste en tweede controller zijn alleen voor het aanbieden van statische HTML-bestanden voor de chat- en inlogpagina's. De derde is voor het afhandelen van het postverzoek naar de /messages   eindpunt voor het maken van nieuwe berichten. In deze controller wordt eerst de request-body geconverteerd naar het Message-model, en vervolgens wordt dit model opgeslagen in de database met behulp van de Mongoose-functie save . 

Ik zal niet veel in Mongoose duiken - je kunt de documentatie bekijken voor meer informatie. U kunt een terugbelfunctie voor de opslagfunctie bieden om te controleren of er een probleem is of niet. Als het is gelukt, hebben we de laatste vijf records opgehaald, in aflopende volgorde gesorteerd op createDate , en hebben vijf berichten naar de clients in het kanaal uitgezonden.

Oké, we zijn klaar met MC .  Laten we overschakelen naar de View onderdeel.

2.3. Bekijk

Over het algemeen kan een template-engine zoals Jade, EJS, Handlebars, etc. binnen Express worden gebruikt. We hebben echter maar één pagina, en dat is een chatbericht, dus ik zal dit statisch weergeven. Zoals ik hierboven al zei, zijn er eigenlijk nog twee controllers om deze statische HTML-pagina weer te geven. U kunt het volgende zien voor het weergeven van een statische HTML-pagina.

app.get('/chat', function(req, res){

    res.sendFile(__dirname + '/index.html');

});



app.get('/login', function(req, res){

    res.sendFile(__dirname + '/login.html');

});

Dit eindpunt dient eenvoudig index.html en login.html door gebruik te maken van res.sendFile . Beide  index.html en login.html bevinden zich in dezelfde map als server.js, daarom hebben we __dirname gebruikt voor de HTML-bestandsnaam.

2.4. Front-end

Op de front-end pagina heb ik Bootstrap gebruikt en het is niet nodig om uit te leggen hoe ik dat voor elkaar heb gekregen. Ik heb gewoon een functie aan een tekstvak gebonden en telkens wanneer u op de Enter  . drukt, sleutel of Verzenden  knop, wordt het bericht naar de back-endservice gestuurd.

Deze pagina heeft ook een vereist js-bestand van Socket.IO om naar het kanaal met de naam message te luisteren . De Socket.IO-module is al geïmporteerd in de back-end en wanneer u deze module aan de serverzijde gebruikt, voegt deze automatisch een eindpunt toe voor het serveren van het Socket.IO js-bestand, maar we gebruiken degene die wordt bediend vanaf cdn <script src="//cdn.socket.io/socket.io-1.3.5.js"></script> . Telkens wanneer een nieuw bericht op dit kanaal binnenkomt, wordt dit automatisch gedetecteerd en wordt de berichtenlijst vernieuwd met de laatste vijf berichten.

<script>

        var socket = io();

        socket.on("message", function (messages) {

            refreshMessages(messages);

        });



        function refreshMessages(messages) {

            $(".media-list").html("");

            $.each(messages.reverse(), function(i, message) {

                $(".media-list").append('<li class="media"><div class="media-body"><div class="media"><div class="media-body">'

                + message.message + '<br/><small class="text-muted">' + message.author + ' | ' + message.createDate + '</small><hr/></div></div></div></li>');

            });

        }



        $(function(){



            if (typeof $.cookie("realtime-chat-nickname") === 'undefined') {

                window.location = "/login"

            } else {

                $.get("/messages", function (messages) {

                    refreshMessages(messages)

                });



                $("#sendMessage").on("click", function() {

                    sendMessage()

                });



                $('#messageText').keyup(function(e){

                    if(e.keyCode == 13)

                    {

                        sendMessage();

                    }

                });

            }



            function sendMessage() {

                $container = $('.media-list');

                $container[0].scrollTop = $container[0].scrollHeight;

                var message = $("#messageText").val();

                var author = $.cookie("realtime-chat-nickname");

                $.post( "/messages", {message: message, author: author}, function( data ) {

                    $("#messageText").val("")

                });

                $container.animate({ scrollTop: $container[0].scrollHeight }, "slow");

            }

        })

    </script>

Er is nog een vinkje in de bovenstaande code:het cookie-gedeelte. Als je geen bijnaam voor chat hebt gekozen, betekent dit dat de cookie niet is ingesteld voor de bijnaam en dat je automatisch wordt doorgestuurd naar de inlogpagina.

Zo niet, dan worden de laatste vijf berichten opgehaald door een simpele Ajax-oproep naar de /messages eindpunt. Op dezelfde manier, wanneer u op de Verzenden . klikt of druk op de Enter key, wordt het sms-bericht opgehaald uit het tekstvak en wordt de bijnaam uit de cookie gehaald, en die waarden worden met een postverzoek naar de server verzonden. Er is hier geen strikte controle op de bijnaam, omdat ik me wilde concentreren op het realtime gedeelte, niet op het gedeelte voor gebruikersauthenticatie.

Zoals u kunt zien, is de algemene structuur van het project heel eenvoudig. Laten we naar het implementatiegedeelte komen. Zoals ik al eerder zei, zullen we Modulus gebruiken, een van de beste PaaS voor het implementeren, schalen en monitoren van uw applicatie in de taal van uw keuze.

3. Implementatie

3.1. Vereisten

Het eerste dat in me opkomt, is om je te laten zien hoe je moet implementeren, maar voor een succesvolle implementatie hebben we een werkende database nodig. Laten we eens kijken hoe u een database op Modulus kunt maken en vervolgens de implementatie kunt uitvoeren.

Ga na het aanmaken van een account naar het Modulus dashboard. Klik op de Databases  menu aan de linkerkant en klik op Database maken.

Vul de vereiste velden in het pop-upformulier in, zoals hieronder.

Wanneer u de vereiste velden invult en op Maken klikt,  het zal een MongoDB-database voor u maken en u zult uw database-URL op het scherm zien. We gebruiken MONGO URI ,  dus kopieer die URI.

In ons project wordt Mongo URI opgehaald uit de omgevingsvariabele MONGO_URI , en u moet die omgevingsvariabele in het dashboard instellen. Ga naar het dashboard, klik op de Projecten menu, selecteer uw project in de lijst en klik op Beheer in het linkermenu. Op deze pagina ziet u het gedeelte met omgevingsvariabelen wanneer u naar beneden scrolt, zoals hieronder weergegeven.

U kunt op twee manieren op Modulus implementeren: 

  • het ZIP-bestand van het project uploaden via het dashboard
  • implementatie vanaf de opdrachtregel met behulp van Modulus CLI

Ik zal doorgaan met de opdrachtregeloptie, omdat de andere gemakkelijk te doen is. Installeer eerst Modulus CLI:

npm install -g modulus

Ga naar uw projectmap en voer de volgende opdracht uit om u aan te melden bij Modulus.

modulus login

Wanneer u de bovenstaande opdracht uitvoert, wordt u gevraagd een gebruikersnaam en wachtwoord in te voeren:

Als je een account hebt gemaakt met GitHub, kun je de --github gebruiken optie.

modulus login --github

Nu bent u aangemeld bij Modulus en is het tijd om een ​​project aan te maken. Gebruik de volgende opdracht om een ​​project aan te maken:

modulus project create "Realtime Chat"

Wanneer u deze functie uitvoert, wordt u om de runtime gevraagd. Selecteer de eerste optie, Node.js, en ten tweede wordt u om de servogrootte gevraagd en kunt u deze als standaard behouden.

We hebben een project gemaakt en deze keer zullen we ons huidige project implementeren in Modulus. Voer de volgende opdracht uit om het huidige project naar de Realtime Chat . te sturen project aan de Modulus-kant.

modulus deploy

Het zal uw project implementeren en u krijgt uw lopende project-URL aan het einde van het bericht over succesvolle implementatie:

Realtime Chat running at realtime-chat-46792.onmodulus.net

Zoals u kunt zien, is de implementatie naar Modulus heel eenvoudig!

Modulus CLI heeft zeer nuttige opdrachten die u kunt gebruiken tijdens uw projectimplementatie of tijdens runtime. Om bijvoorbeeld logs van uw lopende project te volgen, kunt u modulus project logs tail gebruiken , om een ​​MongoDB-database te maken, gebruikt u modulus mongo create <db-name> , om een ​​omgevingsvariabele in te stellen, gebruik modulus env set <key> <value> , enz. U kunt een volledige lijst met opdrachten bekijken met behulp van Modulus help.


  1. Bestand doorgeven aan actieve taak / achtergrondtaak

  2. Zoek en tel elementen van verzameling met Mongoose

  3. MongoDB $isoWeek

  4. Waarom heeft Redis Pub/Sub-mogelijkheden?