Mongoose:无法使用$ addToSet或$ push将新对象添加/推送到数组
我使用Nodejs,Hapijs和Mongoose。
我有一个模式和模型如下。
var schema = {
name: {
type: String,
required: true
},
lectures: {}
};
var mongooseSchema = new mongoose.Schema(schema, {
collection: "Users"
});
mongoose.model("Users", mongooseSchema);
出于某种原因,我需要将“讲座”保持为混合型。
在保存/创建文档时,我创建了一个嵌套的属性lectures.physics.topic [] ,其中topic是一个数组。
现在,我试图使用$ addToSet或$ push将一个新对象添加到“lectures.physics.topic”中。
userModel.findByIdAndUpdateAsync(user._id, {
$addToSet: {
"lectures.physics.topic": {
"name": "Fluid Mechanics",
"day": "Monday",
"faculty": "Nancy Wagner"
}
}
});
但该文件根本没有得到更新。 我也试过使用$ push。 没有工作。 可能是什么问题呢?
我尝试了另一种使用mongoclient的方法,直接更新数据库。它的工作原理请查找下面的代码
db.collection("Users").update({
"_id": user._id
}, {
$addToSet: {
"lectures.physics.topic": {
"name": "Fluid Mechanics",
"day": "Monday",
"faculty": "Nancy Wagner"
}
}
}, function(err, result) {
if (err) {
console.log("Superman!");
console.log(err);
return;
}
console.log(result);
});
每次发出请求时,我都必须启动mongo客户端。这不是一个可行的解决方案。
我会为此调用“bug”。 如后面所示,猫鼬显然在做错事情,如日志中所证明的那样。 但是这里有一个列表,它调用本地驱动程序中的.findOneAndUpdate()
,它与您尝试执行的更新相同:
var async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/school');
mongoose.set('debug',true);
var userSchema = new Schema({
name: {
type: String,
required: true
},
lectures: { type: Schema.Types.Mixed }
});
var User = mongoose.model( "User", userSchema );
function logger(data) {
return JSON.stringify(data, undefined, 2);
}
async.waterfall(
[
function(callback) {
User.remove({},function(err) {
callback(err);
});
},
function(callback) {
console.log("here");
var user = new User({ "name": "bob" });
user.save(function(err,user) {
callback(err,user);
});
},
function(user,callback) {
console.log("Saved: %s", logger(user));
User.collection.findOneAndUpdate(
{ "_id": user._id },
{
"$addToSet": {
"lectures.physics.topic": {
"name": "Fluid Mechanics",
"day": "Monday",
"faculty": "Nancy Wagner"
}
}
},
{ "returnOriginal": false },
function(err,user) {
callback(err,user);
}
);
}
],
function(err,user) {
if (err) throw err;
console.log("Modified: %s", logger(user));
mongoose.disconnect();
}
);
这与结果完美结合:
Saved: {
"__v": 0,
"name": "bob",
"_id": "55cda1f5b5ee8b870e2f53bd"
}
Modified: {
"lastErrorObject": {
"updatedExisting": true,
"n": 1
},
"value": {
"_id": "55cda1f5b5ee8b870e2f53bd",
"name": "bob",
"__v": 0,
"lectures": {
"physics": {
"topic": [
{
"name": "Fluid Mechanics",
"day": "Monday",
"faculty": "Nancy Wagner"
}
]
}
}
},
"ok": 1
}
您需要小心,因为本机驱动程序方法不像猫鼬方法那样知道连接状态。 所以你需要确保一个连接已经由一个“mongoose”方法发起,或者将你的应用包装在连接事件中,如下所示:
mongoose.connection.on("connect",function(err) {
// start app in here
});
至于“bug”,请看这个清单的日志输出:
var async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/school');
mongoose.set('debug',true);
var userSchema = new Schema({
name: {
type: String,
required: true
},
lectures: { type: Schema.Types.Mixed }
});
var User = mongoose.model( "User", userSchema );
function logger(data) {
return JSON.stringify(data, undefined, 2);
}
async.waterfall(
[
function(callback) {
User.remove({},function(err) {
callback(err);
});
},
function(callback) {
console.log("here");
var user = new User({ "name": "bob" });
user.save(function(err,user) {
callback(err,user);
});
},
function(user,callback) {
console.log("Saved: %s", logger(user));
User.findByIdAndUpdate(
user._id,
{
"$addToSet": {
"lectures.physics.topic": {
"name": "Fluid Mechanics",
"day": "Monday",
"faculty": "Nancy Wagner"
}
}
},
{ "new": true },
function(err,user) {
callback(err,user);
}
);
}
],
function(err,user) {
if (err) throw err;
console.log("Modified: %s", logger(user));
mongoose.disconnect();
}
);
和猫鼬日志记录的日志输出:
Mongoose: users.remove({}) {}
here
Mongoose: users.insert({ name: 'bob', _id: ObjectId("55cda2d2462283c90ea3f1ad"), __v: 0 })
Saved: {
"__v": 0,
"name": "bob",
"_id": "55cda2d2462283c90ea3f1ad"
}
Mongoose: users.findOne({ _id: ObjectId("55cda2d2462283c90ea3f1ad") }) { new: true, fields: undefined }
Modified: {
"_id": "55cda2d2462283c90ea3f1ad",
"name": "bob",
"__v": 0
}
所以在真正的“福吉是什么?” 风格,有一个电话到.findOne()
? 这不是被问到的。 此外,当然数据库中没有任何变化,因为错误的呼叫被做出。 所以即使是{ "new": true }
也是多余的。
这发生在所有级别的“混合”模式类型。
就我个人而言,我不会像这样嵌套在“对象”中,只需将标准数组的“对象键”部分作为附加属性即可。 MongoDB和mongoose都非常高兴,而且用这种结构查询信息要容易得多。
var async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/school');
mongoose.set('debug',true);
var lectureSchema = new Schema({
"subject": String,
"topic": String,
"day": String,
"faculty": String
});
var userSchema = new Schema({
name: {
type: String,
required: true
},
lectures: [lectureSchema]
});
var User = mongoose.model( "User", userSchema );
function logger(data) {
return JSON.stringify(data, undefined, 2);
}
async.waterfall(
[
function(callback) {
User.remove({},function(err) {
callback(err);
});
},
function(callback) {
console.log("here");
var user = new User({ "name": "bob" });
user.save(function(err,user) {
callback(err,user);
});
},
function(user,callback) {
console.log("Saved: %s", logger(user));
User.findByIdAndUpdate(
user._id,
{
"$addToSet": {
"lectures": {
"subject": "physics",
"topic": "Fluid Mechanics",
"day": "Monday",
"faculty": "Nancy Wagner"
}
}
},
{ "new": true },
function(err,user) {
callback(err,user);
}
);
}
],
function(err,user) {
if (err) throw err;
console.log("Modified: %s", logger(user));
mongoose.disconnect();
}
);
输出:
Mongoose: users.remove({}) {}
here
Mongoose: users.insert({ name: 'bob', _id: ObjectId("55cda4dc40f2a8fb0e5cdf8b"), lectures: [], __v: 0 })
Saved: {
"__v": 0,
"name": "bob",
"_id": "55cda4dc40f2a8fb0e5cdf8b",
"lectures": []
}
Mongoose: users.findAndModify({ _id: ObjectId("55cda4dc40f2a8fb0e5cdf8b") }) [] { '$addToSet': { lectures: { faculty: 'Nancy Wagner', day: 'Monday', topic: 'Fluid Mechanics', subject: 'physics', _id: ObjectId("55cda4dc40f2a8fb0e5cdf8c") } } } { new: true, upsert: false, remove: false }
Modified: {
"_id": "55cda4dc40f2a8fb0e5cdf8b",
"name": "bob",
"__v": 0,
"lectures": [
{
"faculty": "Nancy Wagner",
"day": "Monday",
"topic": "Fluid Mechanics",
"subject": "physics",
"_id": "55cda4dc40f2a8fb0e5cdf8c"
}
]
}
所以这个工作正常,你不需要挖掘本地方法来使它工作。
数组的属性可以很容易地查询和过滤,以及跨数据“聚合”信息,对于所有这些MongoDB而言,它们都喜欢使用“严格路径”来引用所有信息。 否则,你只能区分“特定键”,而不能提及每个可能的“键组合”都不能进行索引或真正搜索。
像这样的属性是更好的方法。 这里没有错误。
Mongoose失去了自动检测和保存对混合类型所做更改的功能,因此您需要通过调用文档的.markModified(path)
方法来将“混合类型”的值传递给“混合类型”,从而“通知”混合类型的值已更改你只是改变了:
doc.mixed.type = 'changed';
doc.markModified('mixed.type');
doc.save() // changes to mixed.type are now persisted
在你的情况,你可以使用findById()
方法调用进行更改addToSet()
的话题阵列上的方法,然后触发save()
方法来持久的变化:
userModel.findById(user._id, function (err, doc){
var item = {
"name": "Fluid Mechanics",
"day": "Monday",
"faculty": "Nancy Wagner"
};
doc.lectures.physics.topic.addToSet(item);
doc.markModified('lectures');
doc.save() // changes to lectures are now persisted
});
链接地址: http://www.djcxy.com/p/28141.html
上一篇: Mongoose: Not able to add/push a new object to an array with $addToSet or $push