javascript - Sails.js:模型本身的一对多关系

标签 javascript angularjs node.js mongodb sails.js

我正在尝试使用 Sails.js 和 MongoDB 构建一个支持多级类别的简单应用程序。一个类别可以有很多子类别。所以在我的 Category 模型中,我在 Category 内部建立了一对多关系:

module.exports = {

  adapter: 'mongo',

  attributes: {
    categoryTitle: {
      type: 'string',
      required: true
    },

//owner or parent of the one-to-many relationship
parentCat: {
  model: 'category'
},

//sub categories
subCategories: {
  collection: 'category',
  via: 'parentCat'
},
  }};

类别显示在使用 AngularJS 中的 ng-repeat 指令的选择下拉列表中,例如

<select class="selector3" id="categoryParent" ng-model="category.parent">
                <option>Choose a category or none</option>
                <option ng-repeat="cat in categories" value="{{cat.categoryTitle}}">{{cat.categoryTitle}}</option>
            </select>

AngularJS CategoryController 中,我使用 $scope.category.parent 来捕获所选类别(作为父类别)的值。此步骤有效,因为我能够通过 console.log($scope.category.parent); 查看所选值。

但是,当我将新类别及其父类别一起保存到 MongoDB 时,尽管其他字段已正确保存,但父类别为 null,如 Mongo 终端中所示。 我猜问题出在我为在 Sails 中保存新类别而编写的“创建”API。您能找出以下代码中哪里可能有问题吗?

create: function(req, res, next) {
var params = req.allParams();

// set parent category if exists
if (params.parentCat) {

    var parentCategory = Category.findOne({categoryTitle : params.parentCat})
        .exec(function(err, category) {
        if (err) {
            return null; //not found
        }

        return category; //found, return the category
    });

    params.parentCat = parentCategory;  //set the parent category in params
}

//insert the new category to MongoDB
Category.create(params, function(err, category) {
    if (err) {
        console.log('category addition failed');
        return next(err);
    }
    console.log('successfully added the category: ' + category.categoryTitle);
    res.redirect('/category');
});

} //create

最佳答案

您在这里混淆了一些概念。

首先

var parentCategory = Category.findOne({categoryTitle : params.parentCat})

请注意,waterline 方法 findOne 不会从数据库返回文档。因此,上面的陈述不会为您提供您想要达到的目的。重要的是您在 exec 函数中提供的回调函数。可以这样想:

Node.js 事件循环将只执行 Category.findOne 并继续执行下一条语句,而无需等待 findOne 的完成。这里的下一条语句是:

params.parentCat = parentCategory

请注意,从 MongoDB 获取数据尚未完成。即使完成,findOne 也不会像我上面所说的那样返回对数据库中文档的引用。所以,这不是 Node.js 的处理方式。相反,如果你想访问数据库对象,它存在于 exec 回调函数的类别变量中。

现在第二个问题是下面的语句

return category;

如您所知,return 将使您完全脱离创建操作。另外,这里需要注意的一个有趣的一点是,这条语句和底部的重定向语句之间会有竞争。这是为什么

Node.js 事件循环执行它遇到的每个语句。如果该语句是阻塞语句(如 var x = <some computation without callback function> ),那么它将停留在该语句并等待其完成。否则,如果语句是带有回调函数的异步语句(如 Category.findOne({}).exec(function (err, category){}) ),则事件循环将移至下一条语句,并且回调将在 findOne 完成时执行。

现在,在这种情况下,findOne 将被执行,事件循环将转到

params.parentCat = parentCategory; 

这不是异步语句,但它会立即完成并且事件循环继续进行

Category.create()

现在,您可以认为 findOne 和 create 都将在 mongoDB 中并行执行。一旦他们的数据库操作完成,回调函数将被执行。无论哪个回调先执行,它的 return 语句都会被执行。因此,这里的行为是不可预测的。 return category可能会执行或 res.redirect('/category');可能。

我重写了下面的创建函数,保留了上面提到的所有要点

create: function(req, res, next) {
    var params = req.params.all();

    // set parent category if exists
    if (params.parentCat) {
        Category.findOne({categoryTitle : params.parentCat}).exec(function (err, parentCategory) {
            if (err) {
                return res.json(500, 'Sever error'); //not found
            }
            else{
                params.parentCat = parentCategory.id;  //set the parent category in params
                //insert the new category to MongoDB
                Category.create(params, function (err, category) {
                    if (err) {
                        console.log('category addition failed');
                        return next(err);
                    }
                    console.log('successfully added the category: ' + category.categoryTitle);
                    res.redirect('/category');
                });                     
            }
        });
    }
    else{
        return res.json(500,'Server error. Parent category required'); 
    }
}

关于javascript - Sails.js:模型本身的一对多关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27662729/

相关文章:

javascript - 在 OpenLayers 3 中使用编码折线

Javascript Express mongodb服务器无法从发布请求中获取数据

javascript - $routeParam 不通过 $resource 工厂的 url 传递变量

javascript - 有没有办法知道浏览器UI线程是否繁忙?

node.js - 加速 Docker 容器中的 NPM 安装

node.js - 在 NodeJS 服务器中使用导入

javascript - 如何从 Angular JS 中的 get 请求获取输入字段中的数据?

javascript - Jquery ajax() 错误 : "Uncaught Syntax error, unrecognized expression: %2Cacpitool%2Caide"

javascript - 为什么 `var a = ".. ."` 比 `var a = new String(".. .")` 更快?

angularjs - [FromBody] 中的字节数组和 JSON