2012-09-21 6 views
4

J'ai une application node.js en utilisant mongoDB et j'ai une fonction qui est utilisée pour déposer tous les documents dans une collection et ensuite repeupler les collections dans mon db avec quelques exemples de documents.mongoDB getLastError() avec javascript et node.js ne fonctionnant pas

Je l'utilise pour tester mon application avec des données connues de temps en temps lorsque j'écris de nouvelles fonctionnalités. Le problème que je rencontre est que si j'appelle drop() sur toutes mes collections, puis appelez quelques insertions pour repeupler, parfois j'aurai moins d'enregistrements que je m'attends à être inséré dans la base de données et parfois des collections entières seront disparu. mon compte vérifie tous les disques # insérés qui correspondent au montant attendu mais une collection entière pourrait être manquante même si elle dit qu'elle a été insérée. Je ne peux que supposer qu'il ne se passe que 50% du temps que peut-être les inserts commencent à être insérés avant que drop() se termine et que drop() efface les documents insérés car il fonctionne en asynchrone.

J'utilise {safe: true} sur toutes mes commandes d'insertion/mise à jour mais db.collection.drop() ne prend aucun argument et il semble qu'il n'y ait aucun moyen de spécifier une option sûre. Donc j'essaye d'utiliser db.getLastError() après un drop() pour bloquer les insertions jusqu'à ce que la chute se termine.

utilisant db.getLastError() ou db.getlasterror() renvoie une erreur: TypeError: Object # <Db> n'a pas de méthode 'GetLastError'

d'appel simplifié à getLastError:

var mongo = require("mongodb"); 

    var db_conn = new mongo.Db(dbName, new mongo.Server(host, port, { auto_reconnect: true }), {}); 
    db_conn.open(function(err, db) { 
    if(!err) { 
     console.log("Database connection: \033[32mopen\033[0m"); 
    } else { 
     console.log("Database connection: \033[31mfailed\033[0m"); 
    } 
    }); 
    db_conn.getLastError(); 
    this.db_conn = db_conn; 
    this.users = db_conn.collection("users"); 
    this.companies = db_conn.collection("companies"); 
    this.suppliers = db_conn.collection("suppliers"); 

J'ai essayé ceci sur le module mongodb version 1.1.4 et 1.1.7 et ai juste une erreur.

Est-ce que j'utilise une mauvaise référence? Je ne trouve rien sur stackoverflow ou le web en général sur getlasterror dans un exemple de code en JavaScript.

S'il y a une meilleure façon de le faire, je suis tout ouïe.

js docs: http://docs.mongodb.org/manual/reference/javascript/#db.getLastError

mongo docs: http://www.mongodb.org/display/DOCS/getLastError+Command

---- Mise à jour 22 septembre 2012

En utilisant la réponse ci-dessous, j'ai pu déboguer un peu ce que la racine du problème était et il est comme je l'attendais. Avec le pool de connexions par défaut de 5 connexions ouvertes, les gouttes se déclenchent de manière aléatoire et les inserts suivent. En fonction de l'ordre dans lequel ils sont envoyés, et des pools vers lesquels ils vont, si une goutte finit rapidement et insère rapidement une insertion avant la fin de la collecte pour cette collection, elle supprimera les enregistrements insérés plus tard. Ma correction consistait à encapsuler toutes les gouttes dans une séquence de chaînage dans le rappel d'une commande drop() de sorte que chaque drop arrive après que le callback de la précédente drop ait été tiré et ensuite à la fin d'appeler un callback qui se déclenche tous les inserts. C'est désordonné, mais j'ai testé la fonction initializedb maintenant environ 25 fois avec un jeu d'enregistrements de base de 20 insertions simples et avec un test de charge de 100 000 enregistrements. pas encore échoué.

Le temps nous le dira mais cette réponse .lastError() a fonctionné pour résoudre ce problème.

---- Mise à jour Sept 30 2012

Je voulais tester ce pour une semaine avant de répondre pour vous assurer que elle a effectivement travaillé. J'ai exécuté mon script d'initialisation environ 100 fois la semaine dernière à la fois sur un ensemble de base de 26 enregistrements et avec des ensembles de 100 000 enregistrements tous insérés en masse. Je ne l'ai pas vu échouer une fois maintenant en utilisant mon nouveau code.

code-je utiliser pour laisser tomber les collections: (j'ai un objet DatabaseHandler j'utilise avec des fonctions prototypes pour les opérations)

DatabaseHandler.prototype.dropAll = function(callback, callbackArg) { 
    // drop all the documents 
    var that = this; 
    var finished = callback || function() { }; 
    var finishedArg = callbackArg; 
    this.companies.drop(function(err, reply) { 
    if(reply) { 
     console.log("[db] Companies collection dropped"); 
    } else { 
     console.log("\033[31m[Error]\033[0m Companies collection failed to drop"); 
    } 
    // drop all the user documents 
    that.users.drop(function(err, reply) { 
     if(reply) { 
     console.log("[db] Users collection dropped"); 
     } else { 
     console.log("\033[31m[Error]\033[0m Users collection failed to drop"); 
     } 
     // drop all the course documents 
     that.courses.drop(function(err, reply) { 
     if(reply) { 
      console.log("[db] Courses collection dropped"); 
     } else { 
      console.log("\033[31m[Error]\033[0m Courses collection failed to drop"); 
     } 
     // drop all the course purchase documents 
     that.course_purchases.drop(function(err, reply) { 
      if(reply) { 
      console.log("[db] Course purchases collection dropped"); 
      } else { 
      console.log("\033[31m[Error]\033[0m Course purchases collection failed to drop"); 
      } 
      console.log("Dropped all documents and collections"); 
      return finished(finishedArg); 
     }); 
     }); 
    }); 
    }); 
}; 

i ont alors une fonction d'initialisation qui prend un argument pour spécifier si je veux une charge supplémentaire données de test initialize (addloadtestdata). si je spécifie dropdata, il appelle dropAll et prend la fonction initialize pour un callback. Ainsi, lorsque la suppression est terminée, elle appelle le rappel d'initialisation et commence à rajouter des documents uniquement après la fin de la suppression. J'ai également une petite fonction de comptage qui vérifie combien de documents sont insérés après avoir terminé l'insertion ainsi pour vérifier le bon nombre ont été insérés et aucun n'a été manqué. ce fut probablement la meilleure caractéristique i ajoutée de tous si chaque fois que j'initialiser je peux voir si le nombre exact de documents insérés était correcte ou si je manque encore 1.

function initialize(doLoadtest){ 
    // do work here 
} 
// drop all collections and documents 
if(dropdata) { 
    // drop all the data first then call the initialize as a callback function when completed dropping 
    Database.dropAll(initialize, includeLoadtestData); 
} else { 
    initialize(includeLoadtestData); 
} 

espoir qui aide

+0

i ont un problème similaire quand je cours mes tests de mocha. c'est définitivement un problème de timing. J'ai aussi mis '{safe: true}' mais cela ne semble pas faire beaucoup de différence. J'ai mis un 'setTimeout' de 1 seconde pour contourner ce problème (seulement dans le test si). maintenant ça marche 95% du temps. – c0deNinja

+0

pouvez-vous poster le code que vous avez fini par utiliser? – c0deNinja

+0

ajouté l'exemple de code ci-dessus – Dhodgin

Répondre

Questions connexes