2017-05-20 1 views
0

Ich bin neu in MongoDB und arbeite an kleinen Tutorial erstellen Zuordnungen zwischen Tabellen in MongoDB beharrt immer.MongoDB Tabellensätze sind nicht mit ES6 Promise.ALL

Gemäß dem Tutorial, müssen wir Assoziation zwischen drei Tabellen erstellen. 1. Benutzertabelle 2. Blogpost Tabelle 3. Kommentar Tabelle

Benutzer mehrere Blogpost haben und ein Blogpost Liste von Kommentaren und Kommentar kann auch mit Benutzer zugeordnet haben.

Benutzer -> Blogpost -> Kommentar

ich folgenden Testfall geschrieben habe drei Datensätze zu erstellen und die Zuordnung zu testen:

const assert = require('assert'); 
const User = require('../src/users'); 
const BlogPost = require('../src/blogPost'); 
const Comment = require('../src/comment'); 

describe('Association',() => { 
    let ascUer, blogPost, comment; 

    beforeEach((done) => { 
     ascUer = new User({name:'associationUser'}); 

     blogPost = new BlogPost({title:'JS is great',content:'Yep, It is !!'}); 

     comment = new Comment({content:'Congratulation for the great poost !!!'}); 

     ascUer.blogPosts.push(blogPost); 
     blogPost.comments.push(comment); 
     comment.user = ascUer; 

     /* 
     // THIS IS NOT WORKING 
     Promise.all([ascUer.save(),blogPost.save(),comment.save()]) 
      .then(() => done()); 
     */ 

     ascUer.save() 
      .then(() => { 
       console.log('***********Association user saved ***************'); 
       blogPost.save() 
        .then(() => { 
         console.log('***********Blogpost saved ***************'); 
         comment.save() 
          .then(() => { 
           console.log('***********Comment saved ***************'); 
           done(); 
          }); 
        }); 
      }); 
    }); 

    it.only('Saves a relation between a user and a blogpost', (done) => { 
     User.findOne({name:'associationUser'}) 
      .populate('blogPosts') 
      .then((user) => { 
       console.log(user); 
       done(); 
      }); 

    }); 
}); 

ich seltsames Verhalten bin vor, während der Testfall mit Hilfe laufe von Mocha und NodeJs. Der Testfall wird erfolgreich ausgeführt, aber nur die Tabelle "Benutzer" wurde erstellt, während die Funktion "Promise.All" von ES6 verwendet wurde. Ich habe "Promise.All" im obigen Code-Snippet auskommentiert und eins nach dem anderen alle drei Datensätze gespeichert.

Below Bild zeigen Ergebnis Testfall Ausführung: enter image description here

Unten Bild zeigt Schnippen RoboMongo Tool, wo nur "user" Tabelle vorhanden ist: enter image description here

Aktualisiert: Ich habe auch eine erstellt mehr Testfalldatei "connection_helper.js", wo ich "beforeEach" -Block geschrieben habe, um eine DB-Verbindung herzustellen und das gesamte Schema vor der Ausführung von Testfällen zu löschen.

Unten Bild zeigt die Projektverzeichnisstruktur: enter image description here

Und unten ist der Code in "connection_helper" js-Datei geschrieben:

const mongoose = require('mongoose'); 
let isSchemaDropped = false; 

mongoose.Promise = global.Promise; 

before((done) => { 
    mongoose.connect('mongodb://localhost:27017/users_test'); 
    mongoose.connection 
     .once('open',() => { 
      console.log('Connected to Mongose DB !!'); 
      done(); 
     }) 
     .on('error', (error) => { 
      console.warn('Error while connecting to Mongose DB !!',error); 
     }); 

}); 

beforeEach((done) => { 

     if(!isSchemaDropped){ 

      isSchemaDropped = true; 
      console.log("Dropping database schema !!!"); 

      try{ 
       const {users,comments,blogposts,employees} = mongoose.connection.collections; 

       users.drop(() => { 
        comments.drop(() => { 
         blogposts.drop(() => { 
          employees.drop(() => { 
           console.log("**********************************************"); 
           console.log("**********************************************"); 
           console.log("******Dropped All Schema******"); 
           console.log("**********************************************"); 
           console.log("**********************************************"); 

          }); 
         }); 
        }); 
       }); 


      }catch(e){ 
       console.log(e); 
      } 

     }else{ 
      //console.log("Database schema is already dropped before !!!"); 
     } 

     done(); 
}); 

Warum ES6 "Promise.All" funktioniert nicht richtig in mein System? Irgendwelche Vorschläge geschätzt. Sie können meinen Code auch über GitHub beziehen: https://github.com/shahgunjan07/MongoDBTutorial.git für weitere Details.

+0

Ich sehe nicht, warum eigentlich 'Promise.all()' würde scheitern. Ich habe das genaue Schema verwendet, das Sie gepostet haben, und für mich funktioniert 'Promise.all()' einwandfrei, indem Sie wie erwartet drei Sammlungen erstellen. Wo kommt _ "Dropped All Schema" _ her? In Ihrem Protokoll hat das 'User'-Dokument ein leeres 'blogPosts'-Array, aber in Ihrem Robomongo-Screenshot ist eine Objekt-ID zugeordnet. – robertklep

+0

Ich habe test_helper js-Datei geschrieben, wo ich die ganze Tabelle im "beforeEach" -Block ablege. wo ich hinzugefügt habe Log wie "Dropped alle Schema". Der Zweck dieses test_helper besteht darin, eine DB-Verbindung herzustellen und alle vorhandenen Tabellen vor der Ausführung von Testfällen zu löschen. –

Antwort

1

Ich denke, Ihr Problem zu Ihrer beforeEach verwandt ist, die für alle Sammlungen nicht richtig gewartet wird, bevor Sie mit den Tests fallen gelassen werden. Dies kann dazu führen, dass Sammlungen gelöscht werden während Ihre Tests ausgeführt werden, was zu unerwartetem Verhalten führt.

Hier ist eine alternative Implementierung:

beforeEach(() => { 
    if (isSchemaDropped) return; 
    isSchemaDropped = true; 
    console.log("Dropping database schema !!!"); 

    const { 
    users, 
    comments, 
    blogposts, 
    employees 
    } = mongoose.connection.collections; 

    return Promise.all([ 
    users.drop(), 
    comments.drop(), 
    blogposts.drop(), 
    employees.drop() 
    ]); 
}); 
+0

Vorschlag, den Sie erwähnt haben, funktioniert gut.Aber ist es möglich, in diesem Beispiel "done()" anzugeben? –

+0

Gemäß dem Trainingsprogramm sollte der Code, den ich in der Frage erwähnt habe, gut funktionieren. Aber es scheint, dass ich wegen des inkonsistenten Verhaltens von "beforeEach" so vielen Problemen gegenüberstehe. Ist diese Funktion wirklich zuverlässig? Haben wir keine gute Lösung in NodeJS für die synchrone Ausführung? –

+0

@GunjanShah Sie brauchen nicht "fertig", wenn Sie ein Versprechen zurückgeben. Mocha hat eingebaute Versprechungen Unterstützung, die beim Testen (und Arbeiten mit) Versprechungen besser funktioniert. Außerdem weiß ich nicht, welches Trainingsprogramm du meinst, aber der Code in deiner Frage ist _nicht_ in Ordnung. 'beforeEach' ist absolut zuverlässig. Ich denke, Ihre Probleme rühren daher, dass Sie die Feinheiten der asynchronen Programmierung (die ein wesentlicher Bestandteil von Node.js ist) nicht vollständig erfassen. Neuere Versionen von Node (v7 und höher) bieten Konzepte wie ['async/await'] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) ... – robertklep

Verwandte Themen