簡體   English   中英

Sails.js:模型本身的一對多關系

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM