簡體   English   中英

用貓鼬增加數字字段? 用於在.find上對結果進行排序

[英]Increment a number field with Mongoose? For sorting results on .find

我有一個看起來像這樣的貓鼬模型:

module.exports = mongoose.model('Item', {
    text : String,
    position: Number
});

我正在尋找一個位置字段,該字段在所有文檔的.length之類的地方遞增,以便對All .find的結果進行排序:

// get All Items
app.get('/itemsList', function(req, res) {

    // use mongoose to get all items in the database
    Item.find({
        sort : { position: 1 } // sort by Ascending Position
    }. function(err, items) {

        // if there is an error retrieving, send the error. nothing after res.send(err) will execute
        if (err)
            res.send(err)

        res.json(items); // return all items in JSON format
    });
});

有沒有一種方法可以使用node.js中的一些JavaScript自動為Position字段填充數字?

// create an item
app.post('/api/item', function(req, res) {

    // create an item, information comes from AJAX request from Angular
    Item.create({
        text : req.body.text,
        position:
        // something using ++items.length
    }, function(err, item) {
        if (err)
            res.send(err);
    });

});

Mongoose使您可以進入savevalidateremove方法,並在執行之前和之后執行代碼。

該代碼可以是異步的。 例如,您可能會這樣做:

var schema = mongoose.Schema({
    text : String,
    position: Number
});
schema.pre("validate", function(next) {
    var doc = this;

    // If 'position' is not filled in, fill it in.
    // Not using !position because 0 might be a valid value.
    if(typeof position !== "number") {
        // Count the number of Items *
        mongoose.model("Item").count(function(err, num) {
            // If there was an error, pass it to next().
            if(err)
                return next(err);

            // Update the position, then call next();
            doc.position = num;
            return next();
        });
    } else {
        //  There is no need to count, so call next().
        next();
    }
});
module.exports = mongoose.model('Item', schema);

這里更多

在驗證開始之前,將對項目數進行計數。 然后,設置位置。
在上述代碼准備就緒之前,驗證和其他預驗證器**掛鈎將不會開始。

*我在這里使用mongoose.model來獲取模型,因為該模型尚未編譯(在下面發生)。

**文檔向您展示了如何使多個預驗證器掛鈎並行執行。 在本示例中,我選擇不執行此操作,因為代碼更易於閱讀,並且因為您可能實際上需要驗證程序才能按順序運行。


在預驗證掛鈎中,您可以在其他情況下放置一些邏輯。 當插入具有現有position值的Item時,您需要向下移動每條記錄。 您可以通過執行以下操作來做到這一點:

  1. 使用this.isModified("position")檢查自上次保存以來該值是否已更改。 您可能還需要doc.isNew()。
  2. 檢查是否存在相同position的現有文檔。 類似於Item.where({_id: {$ne: this._id}, position: this.position}).count()
  3. 如果存在,請執行: Item.update({position: {$gte: this.position}}, {position: {$inc: 1}}, {multi: 1})
  4. 然后調用next()保存您的文檔。

以上應該可以。 但是,當您刪除文檔時,它將留下空白。

另外,查看索引。 您需要在位置字段中添加一個。 也許甚至是unique index

根據@RikkusRukkus向下移動記錄的步驟,這是else情況(待測試)的邏輯

// load mongoose since we need it to define a schema and model
var mongoose = require('mongoose');

var ItemSchema = mongoose.Schema({
    text : String,
    position: Number
});

// before validation starts, the number of Items is counted..afterwards, the position is set
ItemSchema.pre("validate", function(next) {

    var doc = this;

    // if 'position' is not filled in, fill it in..not using !position because 0 might be a valid value
    if(typeof position !== "number") {
        // count the number of Items *
        // use mongoose.model to fetch the model because the model is not compiled yet
        mongoose.model("Item").count(function(err, num) {
            // if there was an error, pass it to next()
            if(err)
                return next(err);

            // set the position, then call next();
            doc.position = num;
            return next();
        });
    } else if(this.isModified("position") || this.isNew()) {
        // check if there is an existing document with the same position
        // use mongoose.model to fetch the model because the model is not compiled yet
        mongoose.model("Item").where({_id: {$ne: this._id}, position: this.position}).count( function (err, count) {

            // if there was an error, pass it to next()
            if(err)
                return next(err);

            // if there is a doc with the same position, execute an update to move down all the $gte docs
            if(count > 0) {
                // use mongoose.model to fetch the model because the model is not compiled yet
                mongoose.model("Item").update({position: {$gte: this.position}}, {position: {$inc: 1}}, {multi: 1}, function(err, numAffected) {
                    // Call next() (with or without an error)
                    next(err);
                });

            } else {
                //  there are no docs that need to move down, so call next()
                next();
            }
        });
    } else {
        //  there is no need to count or update positions, so call next()
        next();
    }
});

module.exports = mongoose.model('Item', ItemSchema);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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