몽구스에서 문서를 어떻게 업데이트 / 업데이트합니까?
아마도 그것은 아마도 시간 일 것입니다. 아마도 스파 스 문서에 빠져 익사하고 몽구스의 업데이트 개념에 대해 머리를 감쌀 수는 없습니다. :)
거래는 다음과 같습니다.
연락처 스키마 및 모델이 있습니다 (속성 단축).
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);
필요한 필드가 포함 된 클라이언트로부터 요청을 받고 모델을 다음과 같이 사용합니다.
mongoose.connect(connectionString);
var contact = new Contact({
phone: request.phone,
status: request.status
});
이제 우리는 문제에 도달합니다.
- 전화를 걸면
contact.save(function(err){...})
같은 전화 번호를 가진 연락처가 이미 존재하는 경우 오류가 발생합니다 (예상대로-고유) update()
해당 방법이 문서에 없기 때문에 연락 할 수 없습니다- 모델에서 업데이트를 호출
Contact.update({phone:request.phone}, contact, {upsert: true}, function(err{...})
하면 몽구스 업데이트 구현에서 객체를 두 번째 매개 변수로 원하지 않기 때문에 어떤 종류의 무한 루프에 빠지게됩니다. - 내가 똑같이하지만 두 번째 매개 변수에서 요청 속성의 연관 배열을 전달하면
{status: request.status, phone: request.phone ...}
작동하지만 특정 연락처에 대한 참조가 없으며 해당 속성createdAt
과updatedAt
속성을 찾을 수 없습니다 .
결론적으로, 내가 시도한 모든 결론 : document가 주어지면 문서를 contact
업데이트하거나 존재하지 않으면 어떻게 추가합니까?
시간 내 줘서 고마워.
Mongoose는 이제 findOneAndUpdate를 통해이를 기본적으로 지원합니다 (MongoDB findAndModify 호출 ).
upsert = true 옵션은 객체가 존재하지 않는 경우 객체를 만듭니다. 기본값은 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");
});
이전 버전에서 Mongoose는이 방법으로 이러한 후크를 지원하지 않습니다.
- 기본값
- 세터
- 유효성 검사기
- 미들웨어
나는 같은 문제를 해결하기 위해 3 시간 동안 단단하게 태웠다. 특히, 전체 문서가있는 경우 "대체"하거나 그렇지 않으면 삽입하려고했습니다. 해결책은 다음과 같습니다.
var contact = new Contact({
phone: request.phone,
status: request.status
});
// Convert the Model instance to a simple object using Model's 'toObject' function
// to prevent weirdness like infinite looping...
var upsertData = contact.toObject();
// Delete the _id property, otherwise Mongo will return a "Mod on _id not allowed" error
delete upsertData._id;
// Do the upsert, which works like this: If no Contact document exists with
// _id = contact.id, then create a new doc using upsertData.
// Otherwise, update the existing doc with upsertData
Contact.update({_id: contact.id}, upsertData, {upsert: true}, function(err{...});
Mongoose 프로젝트 페이지 에서 이에 대한 정보를 문서에 추가하도록 요청 하는 문제를 만들었습니다 .
당신은 가까이했다
Contact.update({phone:request.phone}, contact, {upsert: true}, function(err){...})
그러나 두 번째 매개 변수는 예를 들어 수정 연산자가있는 객체 여야합니다
Contact.update({phone:request.phone}, {$set: { phone: request.phone }}, {upsert: true}, function(err){...})
글쎄, 나는 오래 기다렸고 대답이 없었다. 마지막으로 전체 업데이트 / 업로드 접근 방식을 포기하고 다음을 수행했습니다.
ContactSchema.findOne({phone: request.phone}, function(err, contact) {
if(!err) {
if(!contact) {
contact = new ContactSchema();
contact.phone = request.phone;
}
contact.status = request.status;
contact.save(function(err) {
if(!err) {
console.log("contact " + contact.phone + " created at " + contact.createdAt + " updated at " + contact.updatedAt);
}
else {
console.log("Error: could not save contact " + contact.phone);
}
});
}
});
작동합니까? 네. 나는 이것에 만족합니까? 아마 아닙니다. 하나 대신 2 개의 DB 호출.
바라건대 미래의 몽구스 구현에는 Model.upsert
기능 이 생길 것입니다 .
약속 체인을 사용하여 달성 할 수있는 매우 우아한 솔루션 :
app.put('url', (req, res) => {
const modelId = req.body.model_id;
const newName = req.body.name;
MyModel.findById(modelId).then((model) => {
return Object.assign(model, {name: newName});
}).then((model) => {
return model.save();
}).then((updatedModel) => {
res.json({
msg: 'model updated',
updatedModel
});
}).catch((err) => {
res.send(err);
});
});
이 질문에 대답하기 위해 StackOverflow 계정 JUST을 만들었습니다. 과일없이 웹을 검색 한 후 나는 방금 뭔가를 썼습니다. 이것이 내가 그렇게 한 방법이므로 모든 몽구스 모델에 적용 할 수 있습니다. 이 함수를 가져 오거나 업데이트중인 코드에 직접 추가하십시오.
function upsertObject (src, dest) {
function recursiveFunc (src, dest) {
_.forOwn(src, function (value, key) {
if(_.isObject(value) && _.keys(value).length !== 0) {
dest[key] = dest[key] || {};
recursiveFunc(src[key], dest[key])
} else if (_.isArray(src) && !_.isObject(src[key])) {
dest.set(key, value);
} else {
dest[key] = value;
}
});
}
recursiveFunc(src, dest);
return dest;
}
그런 다음 몽구스 문서를 업데이트하려면 다음을 수행하십시오.
YourModel.upsert = function (id, newData, callBack) {
this.findById(id, function (err, oldData) {
if(err) {
callBack(err);
} else {
upsertObject(newData, oldData).save(callBack);
}
});
};
이 솔루션에는 2 회의 DB 호출이 필요할 수 있지만 다음과 같은 이점이 있습니다.
- .save ()를 사용하고 있으므로 모델에 대한 스키마 유효성 검사
- 업데이트 호출에서 수동 열거없이 깊게 중첩 된 객체를 업 사트 할 수 있으므로 모델 변경시 코드 업데이트에 대해 걱정할 필요가 없습니다.
소스에 기존 값이 있더라도 대상 객체는 항상 소스를 재정의합니다.
또한 배열의 경우 기존 오브젝트가 대체하는 것보다 긴 배열을 갖는 경우 이전 배열의 끝에있는 값이 유지됩니다. 전체 배열을 upsert하는 쉬운 방법은 이전 배열을 upsert 전에 빈 배열로 설정하는 것입니다.
업데이트-2016 년 1 월 16 일 기본 값 배열이있는 경우 추가 조건을 추가했지만 몽구스는 "set"기능을 사용하지 않고 배열이 업데이트되는 것을 인식하지 못합니다.
문서를 하나의 컬렉션으로 업데이트 / 업데이트해야했습니다. 내가 한 일은 다음과 같이 새 객체 리터럴을 만드는 것입니다.
notificationObject = {
user_id: user.user_id,
feed: {
feed_id: feed.feed_id,
channel_id: feed.channel_id,
feed_title: ''
}
};
데이터베이스의 다른 곳에서 얻은 데이터로 구성된 다음 모델에서 업데이트를 호출합니다.
Notification.update(notificationObject, notificationObject, {upsert: true}, function(err, num, n){
if(err){
throw err;
}
console.log(num, n);
});
이것은 스크립트를 처음 실행 한 후에 얻는 출력입니다.
1 { updatedExisting: false,
upserted: 5289267a861b659b6a00c638,
n: 1,
connectionId: 11,
err: null,
ok: 1 }
그리고 이것은 스크립트를 두 번째로 실행할 때의 결과입니다.
1 { updatedExisting: true, n: 1, connectionId: 18, err: null, ok: 1 }
몽구스 버전 3.6.16을 사용하고 있습니다.
app.put('url', function(req, res) {
// use our bear model to find the bear we want
Bear.findById(req.params.bear_id, function(err, bear) {
if (err)
res.send(err);
bear.name = req.body.name; // update the bears info
// save the bear
bear.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Bear updated!' });
});
});
});
몽구스에서 업데이트 방법을 해결하는 더 좋은 방법은 다음과 같습니다 . 자세한 내용은 Scotch.io 를 확인 하십시오. 이것은 확실히 나를 위해 일했다! !!
2.6에서 소개 된 버그가 있으며 2.7에도 영향을줍니다.
2.4에서 올바르게 작동하는 데 사용되는 upsert
https://groups.google.com/forum/#!topic/mongodb-user/UcKvx4p4hnY https://jira.mongodb.org/browse/SERVER-13843
살펴보면 중요한 정보가 들어 있습니다.
업데이트 :
upsert가 작동하지 않는다는 의미는 아닙니다. 사용 방법에 대한 좋은 예는 다음과 같습니다.
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);
});
당신은 단순히 이것으로 레코드를 업데이트하고 응답으로 업데이트 된 데이터를 얻을 수 있습니다
router.patch('/:id', (req, res, next) => {
const id = req.params.id;
Product.findByIdAndUpdate(id, req.body, {
new: true
},
function(err, model) {
if (!err) {
res.status(201).json({
data: model
});
} else {
res.status(500).json({
message: "not found any relative data"
})
}
});
});
이것은 나를 위해 일했습니다.
app.put('/student/:id', (req, res) => {
Student.findByIdAndUpdate(req.params.id, req.body, (err, user) => {
if (err) {
return res
.status(500)
.send({error: "unsuccessful"})
};
res.send({success: "success"});
});
});
ContactSchema.connection.findOne({phone: request.phone}, function(err, contact) {
if(!err) {
if(!contact) {
contact = new ContactSchema();
contact.phone = request.phone;
}
contact.status = request.status;
contact.save(function(err) {
if(!err) {
console.log("contact " + contact.phone + " created at " + contact.createdAt + " updated at " + contact.updatedAt);
}
else {
console.log("Error: could not save contact " + contact.phone);
}
});
}
});
여기에 도착하는 사람이라면 여전히 후크 지원 기능이있는 "업 세팅"을위한 솔루션을 찾고 있습니다. 이것이 제가 테스트하고 작업 한 것입니다. 여전히 2 개의 DB 호출이 필요하지만 단일 호출에서 시도한 것보다 훨씬 안정적입니다.
// Create or update a Person by unique email.
// @param person - a new or existing Person
function savePerson(person, done) {
var fieldsToUpdate = ['name', 'phone', 'address'];
Person.findOne({
email: person.email
}, function(err, toUpdate) {
if (err) {
done(err);
}
if (toUpdate) {
// Mongoose object have extra properties, we can either omit those props
// or specify which ones we want to update. I chose to update the ones I know exist
// to avoid breaking things if Mongoose objects change in the future.
_.merge(toUpdate, _.pick(person, fieldsToUpdate));
} else {
toUpdate = person;
}
toUpdate.save(function(err, updated, numberAffected) {
if (err) {
done(err);
}
done(null, updated, numberAffected);
});
});
}
다음은 미들웨어 및 유효성 검증기를 호출하면서 작성 / 업데이트하는 가장 간단한 방법입니다.
Contact.findOne({ phone: request.phone }, (err, doc) => {
const contact = (doc) ? doc.set(request) : new Contact(request);
contact.save((saveErr, savedContact) => {
if (saveErr) throw saveErr;
console.log(savedContact);
});
})
//Here is my code to it... work like ninj
router.param('contractor', function(req, res, next, id) {
var query = Contractors.findById(id);
query.exec(function (err, contractor){
if (err) { return next(err); }
if (!contractor) { return next(new Error("can't find contractor")); }
req.contractor = contractor;
return next();
});
});
router.get('/contractors/:contractor/save', function(req, res, next) {
contractor = req.contractor ;
contractor.update({'_id':contractor._id},{upsert: true},function(err,contractor){
if(err){
res.json(err);
return next();
}
return res.json(contractor);
});
});
--
발전기를 사용할 수 있다면 더욱 쉬워집니다.
var query = {'username':this.req.user.username};
this.req.newData.username = this.req.user.username;
this.body = yield MyModel.findOneAndUpdate(query, this.req.newData).exec();
다음 기술 가이 여행 이미 최고, 우리는 플러그인을 작성하고 우리가 그것을 초기화하면 그 있도록 몽구스에 첨부 할 수의 대답, .upsert()
모든 모델에 사용할 수 있습니다.
plugins.js
export default (schema, options) => {
schema.statics.upsert = async function(query, data) {
let record = await this.findOne(query)
if (!record) {
record = new this(data)
} else {
Object.keys(data).forEach(k => {
record[k] = data[k]
})
}
return await record.save()
}
}
db.js
import mongoose from 'mongoose'
import Plugins from './plugins'
mongoose.connect({ ... })
mongoose.plugin(Plugins)
export default mongoose
그런 다음 원하는 때나 원하는 때에 무엇 User.upsert({ _id: 1 }, { foo: 'bar' })
이든 YouModel.upsert({ bar: 'foo' }, { value: 1 })
할 수 있습니다.
잠시 후이 문제로 돌아와서 Aaron Mast의 답변에 따라 플러그인을 게시하기로 결정했습니다.
https://www.npmjs.com/package/mongoose-recursive-upsert
몽구스 플러그인으로 사용하십시오. 전달 된 객체를 재귀 적으로 병합하는 정적 메소드를 설정합니다.
Model.upsert({unique: 'value'}, updateObject});
User.findByIdAndUpdate(req.param('userId'), req.body, (err, user) => {
if(err) return res.json(err);
res.json({ success: true });
});
다른 해결책은 나를 위해 일하지 않았습니다. 게시 요청을 사용하고 데이터를 삽입하면 데이터를 업데이트하고 _id도 제거 해야하는 요청 본문과 함께 전송됩니다.
router.post('/user/createOrUpdate', function(req,res){
var request_data = req.body;
var userModel = new User(request_data);
var upsertData = userModel.toObject();
delete upsertData._id;
var currentUserId;
if (request_data._id || request_data._id !== '') {
currentUserId = new mongoose.mongo.ObjectId(request_data._id);
} else {
currentUserId = new mongoose.mongo.ObjectId();
}
User.update({_id: currentUserId}, upsertData, {upsert: true},
function (err) {
if (err) throw err;
}
);
res.redirect('/home');
});
이 커피 스크립트는 Node와 함께 작동합니다. 트릭은 클라이언트에서 보내고 반환 할 때 _id가 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
Martin Kuzdowicz가 위에 게시 한 내용을 기반으로합니다. 몽구스와 json 객체의 깊은 병합을 사용하여 업데이트를 수행하려면 다음을 사용하십시오. mongoose의 model.save () 함수와 함께 mongoose는 json의 다른 값에 의존하는 전체 검증을 수행 할 수 있습니다. deepmerge 패키지 https://www.npmjs.com/package/deepmerge 가 필요합니다 . 그러나 이것은 매우 가벼운 패키지입니다.
var merge = require('deepmerge');
app.put('url', (req, res) => {
const modelId = req.body.model_id;
MyModel.findById(modelId).then((model) => {
return Object.assign(model, merge(model.toObject(), req.body));
}).then((model) => {
return model.save();
}).then((updatedModel) => {
res.json({
msg: 'model updated',
updatedModel
});
}).catch((err) => {
res.send(err);
});
});
위의 게시물을 읽은 후이 코드를 사용하기로 결정했습니다.
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);
}
});
r이 null이면 새 항목을 만듭니다. 그렇지 않으면 업데이트시 새 항목이 생성되지 않으므로 upsert를 업데이트에 사용하십시오.
참고 URL : https://stackoverflow.com/questions/7267102/how-do-i-update-upsert-a-document-in-mongoose
'Programing' 카테고리의 다른 글
SQL Server-업데이트시 내부 조인 (0) | 2020.03.06 |
---|---|
MySQL-쿼리 속도 테스트를 위해 캐시를 사용하지 마십시오 (0) | 2020.03.06 |
jquery 변경 클래스 이름 (0) | 2020.03.06 |
mysql에 원격 연결을 허용하는 방법 (0) | 2020.03.06 |
C #에서 문자열 암호화 및 암호 해독 (0) | 2020.03.06 |