gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 12:31:07 25 4
gpt4 key购买 nike

我正在尝试使用 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com