本文翻译自:How do I update/upsert a document in Mongoose?
Perhaps it's the time, perhaps it's me drowning in sparse documentation and not being able to wrap my head around the concept of updating in Mongoose :) 也许是时候了,也许是我淹没在稀疏的文档中,无法将自己的头围在Mongoose中的更新概念上:)
Here's the deal: 这是交易:
I have a contact schema and model (shortened properties): 我有一个联系模式和模型(缩短的属性):
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var mongooseTypes = require("mongoose-types"),
useTimestamps = mongooseTypes.useTimestamps;
var ContactSchema = new Schema({
phone: {
type: String,
index: {
unique: true,
dropDups: true
}
},
status: {
type: String,
lowercase: true,
trim: true,
default: 'on'
}
});
ContactSchema.plugin(useTimestamps);
var Contact = mongoose.model('Contact', ContactSchema);
I receive a request from the client, containing the fields I need and use my model thusly: 我从客户端收到一个包含我需要的字段的请求,并因此使用我的模型:
mongoose.connect(connectionString);
var contact = new Contact({
phone: request.phone,
status: request.status
});
And now we reach the problem: 现在我们解决了这个问题:
- If I call
contact.save(function(err){...})
I'll receive an error if the contact with the same phone number already exists (as expected - unique) 如果我致电contact.save(function(err){...})
如果具有相同电话号码的联系人已经存在(如预期-唯一),我将收到一条错误消息 - I can't call
update()
on contact, since that method does not exist on a document 我无法在联系人上调用update()
,因为该方法在文档中不存在 - If I call update on the model: 如果我调用模型更新:
Contact.update({phone:request.phone}, contact, {upsert: true}, function(err{...})
I get into an infinite loop of some sorts, since the Mongoose update implementation clearly doesn't want an object as the second parameter. 我进入某种无限循环,因为Mongoose更新实现显然不希望将对象作为第二个参数。 - If I do the same, but in the second parameter I pass an associative array of the request properties
{status: request.status, phone: request.phone ...}
it works - but then I have no reference to the specific contact and cannot find out itscreatedAt
andupdatedAt
properties. 如果我做同样的事情,但是在第二个参数中,我传递了一个请求属性的关联数组{status: request.status, phone: request.phone ...}
它可以工作-但是我没有引用特定的联系人,并且无法找出其createdAt
和updatedAt
性能。
So the bottom line, after all I tried: given a document contact
, how do I update it if it exists, or add it if it doesn't? 因此,在尝试了所有操作之后,最重要的是:给定一个文档contact
,如果存在它,如何更新它;如果不存在,如何添加它?
Thanks for your time. 谢谢你的时间。
#1楼
参考:https://stackoom.com/question/UUVK/如何在Mongoose中更新-更新文档
#2楼
After reading the posts above, I decided to use this code: 阅读以上内容后,我决定使用此代码:
itemModel.findOne({'pid':obj.pid},function(e,r){
if(r!=null)
{
itemModel.update({'pid':obj.pid},obj,{upsert:true},cb);
}
else
{
var item=new itemModel(obj);
item.save(cb);
}
});
if r is null, we create new item. 如果r为null,则创建新项目。 Otherwise, use upsert in update because update does not create new item. 否则,请在更新中使用upsert,因为更新不会创建新项目。
#3楼
I needed to update/upsert a document into one collection, what I did was to create a new object literal like this: 我需要将文档更新/更新到一个集合中,我要做的是创建一个像这样的新对象文字:
notificationObject = {
user_id: user.user_id,
feed: {
feed_id: feed.feed_id,
channel_id: feed.channel_id,
feed_title: ''
}
};
composed from data that I get from somewhere else in my database and then call update on the Model 由我从数据库其他地方获取的数据组成,然后在模型上调用update
Notification.update(notificationObject, notificationObject, {upsert: true}, function(err, num, n){
if(err){
throw err;
}
console.log(num, n);
});
this is the ouput that I get after running the script for the first time: 这是我第一次运行脚本后得到的输出:
1 { updatedExisting: false,
upserted: 5289267a861b659b6a00c638,
n: 1,
connectionId: 11,
err: null,
ok: 1 }
And this is the output when I run the script for the second time: 这是我第二次运行脚本时的输出:
1 { updatedExisting: true, n: 1, connectionId: 18, err: null, ok: 1 }
I'm using mongoose version 3.6.16 我正在使用猫鼬版本3.6.16
#4楼
This coffeescript works for me with Node - the trick is that the _id get's stripped of its ObjectID wrapper when sent and returned from the client and so this needs to be replaced for updates (when no _id is provided, save will revert to insert and add one). 这个coffeescript对Node来说对我有用-诀窍是_id get从客户端发送和返回时剥去了它的ObjectID包装器,因此需要替换以进行更新(当未提供_id时,保存将恢复为插入和添加一)。
app.post '/new', (req, res) ->
# post data becomes .query
data = req.query
coll = db.collection 'restos'
data._id = ObjectID(data._id) if data._id
coll.save data, {safe:true}, (err, result) ->
console.log("error: "+err) if err
return res.send 500, err if err
console.log(result)
return res.send 200, JSON.stringify result
#5楼
There is a bug introduced in 2.6, and affects to 2.7 as well 2.6中引入了一个错误,该错误也影响到2.7
The upsert used to work correctly on 2.4 该upsert在2.4上正常工作
https://groups.google.com/forum/#!topic/mongodb-user/UcKvx4p4hnY https://jira.mongodb.org/browse/SERVER-13843 https://groups.google.com/forum/#!topic/mongodb-user/UcKvx4p4hnY https://jira.mongodb.org/browse/SERVER-13843
Take a look, it contains some important info 看一下,其中包含一些重要信息
UPDATED: 更新:
It doesnt mean upsert does not work. 这并不意味着upsert不起作用。 Here is a nice example of how to use it: 这是一个很好的用法示例:
User.findByIdAndUpdate(userId, {online: true, $setOnInsert: {username: username, friends: []}}, {upsert: true})
.populate('friends')
.exec(function (err, user) {
if (err) throw err;
console.log(user);
// Emit load event
socket.emit('load', user);
});
#6楼
Mongoose now supports this natively with findOneAndUpdate (calls MongoDB findAndModify ). Mongoose现在通过findOneAndUpdate原生支持此功能 (调用MongoDB findAndModify )。
The upsert = true option creates the object if it doesn't exist. 如果不存在upsert = true选项,则会创建该对象。 defaults to false . 默认为false 。
var query = {'username': req.user.username};
req.newData.username = req.user.username;
MyModel.findOneAndUpdate(query, req.newData, {upsert: true}, function(err, doc) {
if (err) return res.send(500, {error: err});
return res.send('Succesfully saved.');
});
In older versions Mongoose does not support these hooks with this method: 在较旧的版本中,Mongoose不支持使用以下方法的这些钩子:
- defaults 默认值
- setters 二传手
- validators 验证者
- middleware 中间件