[英]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;
}
);
});
);
}
);
};
本质上,尝试了三种可能的操作:
尝试匹配存在类别名称的文档,并更改匹配数组元素的“ UpdatedOn”值。
如果没有更新。 查找与parentId匹配但在数组中不存在类别名称的文档,然后推送一个新元素。
如果没有更新。 执行尝试匹配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.