繁体   English   中英

在mongodb中使用$ addtoset将元素添加到数组

[英]Add elements to array using $addtoset in mongodb

我正在尝试使用addtoset更新集合内的数组的示例。 正在添加新元素,但没有达到预期目的。 根据addtoset,仅当新元素不在列表中时,才添加新元素。

问题:

它只是在添加任何元素。

这是我的代码示例

架构(mongo_database.js):

    var category = new Schema({
    Category_Name: { type: String, required: true},
    //SubCategories: [{}]
    Category_Type: { type: String},
    Sub_Categories: [{Sub_Category_Name: String, UpdatedOn: { type:Date, default:Date.now} }],
    CreatedDate: { type:Date, default: Date.now},
    UpdatedOn: {type: Date, default: Date.now}

});

service.js

exports.addCategory = function (req, res){
//console.log(req.body);
    var category_name = req.body.category_name;
    var parent_category_id = req.body.parent_categoryId;


            console.log(parent_category_id);    
            var cats = JSON.parse('{ "Sub_Category_Name":"'+category_name+'"}');
            //console.log(cats);
            var update = db.category.update(
                { 
                    _id: parent_category_id
                },
                { 
                    $addToSet: { Sub_Categories: cats}
                },
                {
                    upsert:true
                }
            );

            update.exec(function(err, updation){

            })
    }

有人可以帮我解决这个问题吗?

非常感谢..

如前所述, $addToSet不能以这种方式工作,因为数组或“集合”中的元素是要真正代表每个元素完全唯一的“集合”。 此外,诸如.update()类的操作方法不会考虑猫鼬模式的默认设置或验证规则。

但是,诸如.update()类的操作比“查找”文档,然后操纵并使用.save()进行客户端代码中的更改要有效得多。 它们还避免了并发问题,在这些问题中,其他过程或事件操作可能会在检索文档后修改文档。

要执行您想要的操作,需要对服务器进行“多次”更新语句。 我没有一个“后备”逻辑情况,当一个操作不更新文档时,您将后退到下一个:

models / category.js

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

var category = new Schema({
    Category_Name: { type: String, required: true},
    Category_Type: { type: String},
    Sub_Categories: [{Sub_Category_Name: String, UpdatedOn: { type:Date, default:Date.now} }],
    CreatedDate: { type:Date, default: Date.now},
    UpdatedOn: {type: Date, default: Date.now}
});

exports.Category = mongoose.model( "Category", category );

在您的代码中

var Category = require('models/category').Category;

exports.addCategory = function(req,res) {
    var category_name = req.body.category_name;
    var parent_category_id = req.body.parent_categoryId;

    Category.update(
        { 
            "_id": parent_category_id, 
            "Sub_Categories.Sub_Category_Name": category_name
        },
        {
            "$set": { "Sub_Categories.$.UpdatedOn": new Date() }
        },
        function(err,numAffected) {
           if (err) throw error;     // or handle

           if ( numAffected == 0 )
               Category.update(
                   {
                       "_id": parent_category_id, 
                       "Sub_Categories.Sub_Category_Name": { "$ne": category_name }
                   },
                   {
                       "$push": {
                           "Sub_Categories": {
                               "Sub_Category_Name": category_name,
                               "UpdatedOn": new Date()
                           }
                       }
                   },
                   function(err,numAffected) {
                       if (err) throw err;     // or handle

                       if ( numAffected == 0 )
                           Category.update(
                               {
                                   "_id": parent_category_id
                               },
                               { 
                                   "$push": {
                                       "Sub_Categories": {
                                           "Sub_Category_Name": category_name,
                                           "UpdatedOn": new Date()
                                       }
                                   }
                               },
                               { "$upsert": true },
                               function(err,numAffected) {
                                   if (err) throw err;
                               }
                           );
                   });
               );
        }
    );                    
};

本质上,尝试了三种可能的操作:

  1. 尝试匹配存在类别名称的文档,并更改匹配数组元素的“ UpdatedOn”值。

  2. 如果没有更新。 查找与parentId匹配但在数组中不存在类别名称的文档,然后推送一个新元素。

  3. 如果没有更新。 执行尝试匹配parentId的操作,然后将upsert设置为true的数组元素压入。 由于先前的两次更新均失败,因此基本上是插入操作。

您可以通过使用async.waterfall之类的方法来传递numAffected值并避免缩进,或者我个人不愿意检查受影响的值并将所有语句立即通过批量操作API

可以从猫鼬模型访问后者,如下所示:

var ObjectId = mongoose.mongo.ObjectID,
   Category = require('models/category').Category;

exports.addCategory = function(req,res) {
    var category_name = req.body.category_name;
    var parent_category_id = req.body.parent_categoryId;


    var bulk = Category.collection.initializeOrderBulkOp();

    // Reversed insert
    bulk.find({ "_id": { "$ne": new ObjectId( parent_category_id ) })
        .upsert().updateOne({
            "$setOnInsert": { "_id": new ObjectId( parent_category_id ) },
            "$push": {
                "Sub_Category_Name": category_name,
                "UpdatedOn": new Date()
            }
        });

    // In place
    bulk.find({ 
        "_id": new ObjectId( parent_category_id ), 
        "Sub_Categories.Sub_Category_Name": category_name
    }).updateOne({
        "$set": { "Sub_Categories.$.UpdatedOn": new Date() }
    });

    // Push where not matched
    bulk.find({
        "_id": new ObjectId( parent_category_id ), 
        "Sub_Categories.Sub_Category_Name": { "$ne": category_name }
    }).updateOne({
        "$push": {
            "Sub_Category_Name": category_name,
            "UpdatedOn": new Date()
        }
    });

    // Send to server
    bulk.execute(function(err,response) {
        if (err) throw err;    // or handle
        console.log( JSON.stringify( response, undefined, 4 ) );
    });
};

请注意相反的逻辑,其中“ upsert”首先出现,但是如果成功,则仅应用“ second”语句,但实际上在Bulk API下,这不会影响文档。 您将获得一个WriteResult对象,其基本信息与此类似(缩写形式):

{ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }

或在“ upsert”上:

{
    "nMatched" : 1,
    "nUpserted" : 1,
    "nModified" : 0,
    "_id" : ObjectId("54af8fe7628bee196ce97ce0")
}

还要注意,需要包括来自基本mongo驱动程序的ObjectId函数,因为这是来自基本驱动程序的“原始”方法,并且它不像mongoose方法那样基于模式“自动广播”。

此外,请非常小心,因为它是基本驱动程序方法,并且不共享猫鼬逻辑,所以如果尚未建立与数据库的连接,则调用.collection访问器将不会返回Collection对象,并且后续方法调用失败。 猫鼬本身对数据库连接进行“惰性”实例化,并且对方法调用进行“排队”,直到连接可用为止。 基本的驱动程序方法则并非如此。

这样就可以完成,只是您需要自己处理此类数组的逻辑,因为没有本机运算符可以执行此操作。 但是,如果您采取适当的措施,它仍然非常简单并且非常有效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM