我正在尝试使用 addtoset 更新集合中的数组的示例。新元素正在添加但不是预期的。根据{{3}},只有当元素不在列表中时才会添加新元素。
问题:
它只是采取任何元素添加。
这是我的代码示例
架构(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){
})
}
有人可以帮我解决这个问题吗?
非常感谢..答案 0 :(得分:1)
正如已经提到的那样,$addToSet
不能像数组中的元素那样工作,或者" set"意在真正代表" set"每个元素都是独一无二的。此外,.update()
等操作方法不会考虑mongoose架构默认或验证规则。
然而,.update()
等操作比"发现"更有效。该文档,然后操纵并使用.save()
进行客户端代码中的更改。它们还避免了并发问题,其他进程或事件操作可能在检索文档后修改了文档。
做你想做的事情需要制作" mulitple"将语句更新到服务器。我是"后退"逻辑情况,当一个操作没有更新文档时,你回退到下一个:
<强>模型/ 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;
}
);
});
);
}
);
};
基本上可以尝试三种操作:
尝试匹配存在类别名称的文档,并更改&#34; UpdatedOn&#34;匹配数组元素的值。
如果没有更新。查找与parentId匹配但文档中不存在类别名称的文档并推送新元素。
如果没有更新。执行尝试匹配parentId的操作,只需将数组元素与upsert设置为true即可。由于之前的两次更新均失败,因此基本上是插入。
您可以使用async.waterfall之类的内容来传递numAffected
值并避免缩进蠕变,或者个人不喜欢检查受影响的值并通过通过Bulk Operations 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 ) );
});
};
注意反转逻辑,其中&#34; upsert&#34;首先发生,但如果成功,那么只有&#34;第二个&#34;声明将适用,但实际上在Bulk API下这不会影响文档。您将获得一个WriteResult
对象,其基本信息与此类似(以简略形式):
{ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }
或者&#34; upsert&#34;:
{
"nMatched" : 1,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("54af8fe7628bee196ce97ce0")
}
还要注意需要包含基本mongo驱动程序中的ObjectId
函数,因为这是&#34; raw&#34;来自基本驱动程序的方法并没有&#34; autocast&#34;基于像mongoose方法那样的模式。
另外要非常小心,因为它是一个基本的驱动程序方法,并且不共享mongoose逻辑,所以如果没有建立与数据库的连接,那么调用.collection
访问器将不会返回{ {1}}对象和后续方法调用失败。猫鼬本身做了一个懒惰的&#34;数据库连接的即时化,方法调用排队&#34;直到连接可用。基本的驱动程序方法不是这样。
所以它可以完成,只是你需要自己处理这种数组处理的逻辑,因为没有本地运算符可以做到这一点。但如果你采取适当的照顾,它仍然非常简单和有效。