88 votes

Maintenir ouverte une connexion à la base de données MongoDB

Dans de nombreux exemples d'introduction à l'utilisation de MongoDB, vous voyez un code comme celui-ci :

var MongoClient = require('mongodb').MongoClient;
MongoClient.connect("mongodb://localhost:port/adatabase", function(err, db)
{
    /* Some operation... CRUD, etc. */
    db.close();
});

Si MongoDB est comme n'importe quel autre système de base de données, open et close sont généralement coûteuses en termes de temps.

Ma question est donc la suivante : Est-il possible de faire simplement le MongoClient.connect("... une fois, assigner le db à une valeur globale du module, faire en sorte que diverses fonctions du module effectuent divers travaux liés à la base de données (insertion de documents dans des collections, mise à jour de documents, etc. etc.) lorsqu'elles sont appelées par d'autres parties de l'application (et réutiliser ainsi cette valeur db ), puis, lorsque l'application est terminée, ce n'est qu'à ce moment-là que l'on peut utiliser la fonction close .

En d'autres termes, open et close ne sont effectuées qu'une seule fois, et non à chaque fois que vous devez effectuer une opération liée à la base de données. Et vous continuez à réutiliser cette db qui a été renvoyé lors de l'opération initiale de open\connect pour s'en débarrasser à la fin, avec l'aide de la close lorsque vous avez terminé votre travail sur la base de données.

Évidemment, puisque toutes les E/S sont asynchrones, avant que la fonction close vous devez vous assurer que la dernière opération sur la base de données s'est terminée avant de lancer la commande close . Il semble que cela devrait être correct, mais je voulais vérifier au cas où quelque chose m'échapperait, car je suis novice en matière de MongoDB. Merci de votre compréhension.

70voto

Peter Lyons Points 47794

Oui, c'est un comportement normal et typique. Démarrez votre application, connectez-vous à la base de données, effectuez des opérations sur la base de données pendant un long moment, reconnectez-vous éventuellement si la connexion meurt de manière inattendue, et ne fermez jamais la connexion (comptez simplement sur la fermeture automatique qui se produit lorsque votre processus meurt).

15voto

Henry Bothin Points 141

mongodb version ^3.1.8

Initialiser la connexion en tant que promesse :

const MongoClient = require('mongodb').MongoClient
const uri = 'mongodb://...'
const client = new MongoClient(uri)
const connection = client.connect() // initialized connection

Vous pouvez ensuite appeler la connexion chaque fois que vous souhaitez effectuer une action sur la base de données :

    // if I want to insert into the database...
    const connect = connection
    connect.then(() => {
        const doc = { id: 3 }
        const db = client.db('database_name')
        const coll = db.collection('collection_name')
        coll.insertOne(doc, (err, result) => {
            if(err) throw err
        })
    })

5voto

Mihir Patel Points 210

La réponse acceptée actuellement est correcte en ce sens que vous pouvez garder la même connexion à la base de données ouverte pour effectuer des opérations, mais il manque des détails sur la manière dont vous pouvez réessayer de vous connecter si la connexion se ferme. Vous trouverez ci-dessous deux façons de vous reconnecter automatiquement. C'est en TypeScript, mais cela peut facilement être traduit en Node.js normal si vous en avez besoin.

Méthode 1 : Options MongoClient

La façon la plus simple de permettre à MongoDB de se reconnecter est de définir une fonction reconnectTries dans un options lors de son passage dans MongoClient . Chaque fois qu'une opération CRUD est interrompue, elle utilise les paramètres passés dans la fonction MongoClient pour décider de la manière de réessayer (reconnecter). En réglant l'option sur Number.MAX_VALUE fait en sorte qu'il réessaie indéfiniment jusqu'à ce qu'il soit en mesure de terminer l'opération. Vous pouvez consulter le code source du pilote si vous souhaitez connaître les erreurs qui seront retentées.

class MongoDB {
    private db: Db;

    constructor() {
        this.connectToMongoDB();
    }

    async connectToMongoDB() {
        const options: MongoClientOptions = {
            reconnectInterval: 1000,
            reconnectTries: Number.MAX_VALUE
        };

        try {
            const client = new MongoClient('uri-goes-here', options);
            await client.connect();
            this.db = client.db('dbname');
        } catch (err) {
            console.error(err, 'MongoDB connection failed.');
        }
    }

    async insert(doc: any) {
        if (this.db) {
            try {
                await this.db.collection('collection').insertOne(doc);
            } catch (err) {
                console.error(err, 'Something went wrong.');
            }
        }
    }
}

Méthode 2 : Try-catch Retry

Si vous souhaitez une assistance plus granulaire pour les tentatives de reconnexion, vous pouvez utiliser un try-catch avec une boucle while. Par exemple, vous voudrez peut-être consigner une erreur lorsqu'il faut se reconnecter ou vous voudrez faire différentes choses en fonction du type d'erreur. Cela vous permettra également d'effectuer une nouvelle tentative en fonction d'autres conditions que les conditions standard incluses dans le pilote. La fonction insert peut être modifiée comme suit :

async insert(doc: any) {
    if (this.db) {
        let isInserted = false;

        while (isInserted === false) {
            try {
                await this.db.collection('collection').insertOne(doc);
                isInserted = true;
            } catch (err) {
                // Add custom error handling if desired
                console.error(err, 'Attempting to retry insert.');

                try {
                    await this.connectToMongoDB();
                } catch {
                    // Do something if this fails as well
                }
            }
        }
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X