【问题标题】:MongoDB table records are not getting persisted with ES6 Promise.ALLMongoDB 表记录没有被 ES6 Promise.ALL 持久化
【发布时间】:2023-03-18 11:21:01
【问题描述】:

我是 MongoDB 新手,正在编写小教程以在 MongoDB 中创建表之间的关联。

按照教程,我们需要在三个表之间创建关联。 1.用户表 2. BlogPost 表 3.评论表

用户可能有多个博文,一个博文可能有 cmets 列表,评论也与用户映射。

用户 -> 博客帖子 -> 评论

我编写了以下测试用例来创建三个记录并测试关联:

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();
            });

    });
});

在 mocha 和 nodeJs 的帮助下运行测试用例时,我遇到了奇怪的行为。测试用例已成功执行,但在使用 ES6 的“Promise.All”功能时仅创建了“user”表。 上面代码sn-p中我已经注释掉了“Promise.All”,并一一保存了三条记录。

下图显示了测试用例的执行结果:

下图显示了 RoboMongo 工具的快照,其中仅存在“用户”表:

更新:我还创建了一个测试用例文件“connection_helper.js”,我在其中编写了“beforeEach”块来建立数据库连接并在执行任何测试用例之前删除所有模式。

下图显示了项目目录结构:

以下是“connection_helper”js文件中编写的代码:

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();
});

为什么 ES6 "Promise.All" 在我的系统中不能正常工作?任何建议表示赞赏。您也可以在 GitHub 上参考我的代码:https://github.com/shahgunjan07/MongoDBTutorial.git 了解更多详情。

【问题讨论】:

  • 我真的不明白为什么Promise.all() 会失败。我使用了您发布的确切架构,对我来说,Promise.all() 工作得很好,按预期创建了三个集合。 "Dropped All Schema" 来自哪里?在您的日志中,User 文档有一个空的 blogPosts 数组,但在您的 Robomongo 屏幕截图中,它有一个关联的 ObjectId。
  • 我已经编写了 test_helper js 文件,我将在“beforeEach”块中删除所有表。我在其中添加了“删除所有架构”之类​​的日志。此 test_helper 的目的是在执行任何测试用例之前建立数据库连接并删除所有现有表。

标签: node.js mongodb mongoose es6-promise robo3t


【解决方案1】:

我认为您的问题与您的 beforeEach 有关,它没有正确等待所有集合都被删除,然后再继续测试。这可能会导致在您的测试运行时删除集合,从而导致意外行为。

这是一个替代实现:

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()
  ]);
});

【讨论】:

  • 您提到的建议工作正常。但是在这个例子中是否可以在 beforeEach 中提供“done()”?
  • 根据培训计​​划,我在问题中提到的代码应该可以正常工作。但是由于“beforeEach”的行为不一致,我似乎面临着很多问题。这个功能真的可靠吗?我们在nodeJS中没有什么好的同步执行解决方案吗?
  • @GunjanShah 如果你返回一个承诺,你就不需要done。 Mocha 具有内置的 Promise 支持,在测试(和使用)Promise 时效果更好。另外,我不知道您指的是哪个培训计划,但是您问题中的代码很好。 beforeEach 非常可靠,我认为您的问题源于没有完全掌握异步编程的复杂性(这是 Node.js 的基本部分)。较新版本的 Node(v7 及更高版本)提供了类似 async/await... 的概念
  • @GunjanShah ...这将使处理异步代码更容易。但是,它仍然是 Node.js 和 JavaScript 所固有的主题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-27
  • 2012-01-09
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 2013-02-17
  • 1970-01-01
相关资源
最近更新 更多