[英]Sails.js: one-to-many relationship for a model itself
我正在嘗試使用Sails.js和MongoDB來構建一個支持多級別類別的簡單應用程序。 類別可以有許多子類別。 所以在我的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);
查看所選值console.log($scope.category.parent);
。
但是,當我將新類別及其父類別一起保存到MongoDB時, 即使正確保存了其他字段 , 父類別也為null ,如Mongo終端中所示。 我想問題是我用於在Sails中保存新類別的'create'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})
注意,水線方法findOne不會從數據庫返回文檔。 因此,上述聲明不會為您實現您的目的。 重要的是你在exec函數中提供的回調函數。 可以這樣想:
Node.js事件循環將只執行Category.findOne並繼續前進到下一個語句,而無需等待findOne的完成。 這里的下一個陳述是:
params.parentCat = parentCategory
請注意,從MongoDB獲取尚未完成。 即使它已經完成,findOne也不會像我上面所說的那樣返回對數據庫中文檔的引用。 所以,這不是在Node.js中完成任務的方式。 相反,如果要訪問數據庫對象,則其在exec中的回調函數的類別變量中存在。
現在第二個問題是下面的陳述
return category;
如你所知,將完全退出創建動作。 此外,這里需要注意的一點是,此語句與底部的重定向語句之間存在競爭。 這就是原因
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');
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.