복붙노트

[MONGODB] 어떻게 몽구스의 문서 upsert / 업데이트하려면 어떻게해야합니까?

MONGODB

어떻게 몽구스의 문서 upsert / 업데이트하려면 어떻게해야합니까?

아마도 그것은 시간이 아마도 그것은 나를 스파 스 문서에 익사와 몽구스의 갱신의 개념 주위에 내 머리를 정리 할 수있는 아니에요입니다 :)

여기 거래는 다음과 같습니다

나는 접촉 스키마와 모델 (단축 특성)이 있습니다

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);

내가 필요 thusly 히 내 모델을 사용하는 필드를 포함하는, 클라이언트로부터의 요청을 수신 :

mongoose.connect(connectionString);
var contact = new Contact({
    phone: request.phone,
    status: request.status
});

그리고 지금 우리는이 문제에 도달 :

결론 그래서 모든 나는 시도 후 : 문서의 접촉을 주어, 어떻게 존재하는 경우이를 업데이트 않거나, 그렇지 않을 경우 추가?

시간 내 줘서 고마워.

해결법

  1. ==============================

    1.몽구스는 지금이 기본적으로 findOneAndUpdate와 지원 (MongoDB를 findAndModify 호출).

    몽구스는 지금이 기본적으로 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.');
    });
    

    이전 버전에서는 몽구스는이 방법이 후크를 지원하지 않습니다

  2. ==============================

    2.난 그냥 같은 문제를 해결하기 위해 노력 고체 3 시간 불. 특히, 나는 그것이 존재하는 경우 전체 문서를 "대체", 또는 그렇지 않으면 삽입하고 싶었다. 여기에 솔루션입니다 :

    난 그냥 같은 문제를 해결하기 위해 노력 고체 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{...});
    

    나는이이 문서에 추가 할에 대한 그 정보를 요청하는 몽구스 프로젝트 페이지에 문제를 만들었습니다.

  3. ==============================

    3.당신은에 가까웠다

    당신은에 가까웠다

    Contact.update({phone:request.phone}, contact, {upsert: true}, function(err){...})
    

    하지만 두 번째 매개 변수는 예를 들어 수정 연산자 객체이어야한다

    Contact.update({phone:request.phone}, {$set: { phone: request.phone }}, {upsert: true}, function(err){...})
    
  4. ==============================

    4.글쎄, 난 충분히없이 대답을 기다렸다. 마지막으로 전체 업데이트 / upsert 접근 방식을 포기하고 갔다 :

    글쎄, 난 충분히없이 대답을 기다렸다. 마지막으로 전체 업데이트 / upsert 접근 방식을 포기하고 갔다 :

    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);
                }
            });
        }
    });
    

    작동합니까? 네. 나는이 행복 있습니까? 아마 아닙니다. 이 DB는 하나 대신 호출합니다. 희망 미래 몽구스 구현은 Model.upsert 기능을 가지고 올 것입니다.

  5. ==============================

    5.아주 우아한 해결책 당신은 약속의 체인을 사용하여 얻을 수 있습니다 :

    아주 우아한 해결책 당신은 약속의 체인을 사용하여 얻을 수 있습니다 :

    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);
        });
    });
    
  6. ==============================

    6.난 그냥이 질문에 대답하기 위해 StackOverflow의 계정을 만들었습니다. fruitlessly 인터 웹을 검색 한 후 난 그냥 뭔가 나 자신을 썼다. 이것은 어떤 몽구스 모델에 적용 할 수 있도록 내가 한 방법이다. 어느 쪽이 기능을 가져 오거나 사용자가 업데이트를하고있는 곳 코드에 직접 추가 할 수 있습니다.

    난 그냥이 질문에 대답하기 위해 StackOverflow의 계정을 만들었습니다. fruitlessly 인터 웹을 검색 한 후 난 그냥 뭔가 나 자신을 썼다. 이것은 어떤 몽구스 모델에 적용 할 수 있도록 내가 한 방법이다. 어느 쪽이 기능을 가져 오거나 사용자가 업데이트를하고있는 곳 코드에 직접 추가 할 수 있습니다.

    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;
    }
    

    그런 다음 몽구스 문서는 다음을 수행 upsert하기 위해,

    YourModel.upsert = function (id, newData, callBack) {
      this.findById(id, function (err, oldData) {
        if(err) {
          callBack(err);
        } else {
          upsertObject(newData, oldData).save(callBack);
        }
      });
    };
    

    이 솔루션은, 당신의 혜택을받을 수 있나요 그러나 2 DB 호출을 요구할 수있다

    그냥 소스가 기존의 값을 갖는 경우에도 대상 객체는 항상 소스를 재정의합니다 기억

    또한, 배열을 위해, 기존의 객체는 기존 배열의 끝에 값이 유지됩니다 그것을 대체하는 것보다 더 긴 배열이있는 경우. 전체 배열을 upsert하는 쉬운 방법은 당신이 일을하고자하는 것입니다 경우 upsert 전에 빈 배열로 기존의 배열을 설정하는 것입니다.

    UPDATE - 2016년 1월 16일 프리미티브 값의 배열이 있다면 몽구스 배열이 "세트"기능을 사용하지 않고 업데이트된다 깨닫지 못하고위한 I은 추가 조건을 밝혔다.

  7. ==============================

    7.나는 하나 개의 모음으로 문서 upsert / 업데이트해야, 내가 한 일은이 같은 새 개체 리터럴을 만드는 것이 었습니다 :

    나는 하나 개의 모음으로 문서 upsert / 업데이트해야, 내가 한 일은이 같은 새 개체 리터럴을 만드는 것이 었습니다 :

    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을 사용하고 있습니다

  8. ==============================

    8.

    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를 확인할 수 있습니다. 이것은 확실히 나를 위해 일한!

  9. ==============================

    9.이 2.6에 도입 된 버그이며,뿐만 아니라 2.7에 영향을

    이 2.6에 도입 된 버그이며,뿐만 아니라 2.7에 영향을

    upsert 2.4에서 제대로 작동하는 데 사용

    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);
        });
    
  10. ==============================

    10.이 날 위해 일했습니다.

    이 날 위해 일했습니다.

    app.put ( '/ 학생 / : 아이디'(REQ, 고해상도) => {     Student.findByIdAndUpdate (req.params.id, req.body (ERR, 사용자) => {         경우 (ERR) {             반환 고해상도                 .STATUS (500)                 .send ({오류 : "실패"})         };         ({성공 "성공"}) res.send;     }); });

  11. ==============================

    11.당신은 단순히 이것으로 기록을 갱신하고 응답 업데이트 된 데이터를 얻을 수 있습니다

    당신은 단순히 이것으로 기록을 갱신하고 응답 업데이트 된 데이터를 얻을 수 있습니다

    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"
                    })
                }
            });
    });
    
  12. ==============================

    12.여전히 이익을 위해 후크 지원 "upserting"에 대한 해결책을 찾고 여기에 도착 누군가를 위해, 이것은 내가 테스트 작업을 한 것입니다. 아직 2 DB 호출을 필요로하지만 단일 통화 시도했습니다 무엇보다 훨씬 더 안정적이다.

    여전히 이익을 위해 후크 지원 "upserting"에 대한 해결책을 찾고 여기에 도착 누군가를 위해, 이것은 내가 테스트 작업을 한 것입니다. 아직 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);
        });
      });
    }
    
  13. ==============================

    13.발전기를 사용할 수있는 경우가 훨씬 더 쉬워집니다 :

    발전기를 사용할 수있는 경우가 훨씬 더 쉬워집니다 :

    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();
    
  14. ==============================

    14.여기에 또한 미들웨어 및 유효성 검사기를 호출하는 동안 / 업데이트를 만들 수있는 간단한 방법입니다.

    여기에 또한 미들웨어 및 유효성 검사기를 호출하는 동안 / 업데이트를 만들 수있는 간단한 방법입니다.

    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);
        });
    })
    
  15. ==============================

    15.

    //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); 
      });
    });
    
    
    --
    
  16. ==============================

    16.이미 멋진, 우리는 플러그인을 작성하고 우리가 .upsert 있도록를 초기화하면 몽구스에 첨부 할 수 테크 가이의 대답을, 여행 다음 () 모든 모델에서 사용할 수 있습니다.

    이미 멋진, 우리는 플러그인을 작성하고 우리가 .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는 '바'}) 또는 YouModel.upsert ({바 'foo는'}, {값 : 1}) 당신이 원하는 때마다합니다.

  17. ==============================

    17.난 그냥 잠시 후 다시이 문제에 다가서는 듯 아론 마스트로 답변에 따라 플러그인을 게시하기로 결정했다.

    난 그냥 잠시 후 다시이 문제에 다가서는 듯 아론 마스트로 답변에 따라 플러그인을 게시하기로 결정했다.

    https://www.npmjs.com/package/mongoose-recursive-upsert

    몽구스 플러그인으로 사용합니다. 그것은 반복적으로 전달 된 객체를 병합하는 정적 방법을 설정합니다.

    Model.upsert({unique: 'value'}, updateObject});
    
  18. ==============================

    18.

    User.findByIdAndUpdate(req.param('userId'), req.body, (err, user) => {
        if(err) return res.json(err);
    
        res.json({ success: true });
    });
    
  19. ==============================

    19.다른 솔루션은 나를 위해 일하지 않는다. 나는 POST 요청을 사용하여 다른 발견이 삽입도 제거 할 필요가있어 요청 본문에 _id 전송되는 경우 데이터를 업데이트하고 있습니다.

    다른 솔루션은 나를 위해 일하지 않는다. 나는 POST 요청을 사용하여 다른 발견이 삽입도 제거 할 필요가있어 요청 본문에 _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');
    
    });
    
  20. ==============================

    20.노드와 나를 위해이 커피 스크립트 작품 - 트릭은 전송 및 클라이언트에서 더 _id가 제공되지 않은 경우이 필요 (업데이트를 대체 할 수 있도록 돌아 왔을 때 삽입하고 추가 할 되돌아갑니다 퇴피 _id GET의, 그 OBJECTID 래퍼의 박탈이다 하나).

    노드와 나를 위해이 커피 스크립트 작품 - 트릭은 전송 및 클라이언트에서 더 _id가 제공되지 않은 경우이 필요 (업데이트를 대체 할 수 있도록 돌아 왔을 때 삽입하고 추가 할 되돌아갑니다 퇴피 _id GET의, 그 OBJECTID 래퍼의 박탈이다 하나).

    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
    
  21. ==============================

    21.빌드 작업에 마틴 Kuzdowicz 위 기록했다. 나는 몽구스와 JSON 개체의 완전 병합을 사용하여 갱신을 수행하려면 다음을 사용합니다. 이 몽구스 전체 유효성 검사 JSON에서 다른 값에 의존 심지어 하나를 수행 할 수 있습니다 몽구스의 model.save () 함수와 함께. 그것은 deepmerge 패키지 https://www.npmjs.com/package/deepmerge을 필요로한다. 그러나 그것은 매우 가벼운 무게 패키지입니다.

    빌드 작업에 마틴 Kuzdowicz 위 기록했다. 나는 몽구스와 JSON 개체의 완전 병합을 사용하여 갱신을 수행하려면 다음을 사용합니다. 이 몽구스 전체 유효성 검사 JSON에서 다른 값에 의존 심지어 하나를 수행 할 수 있습니다 몽구스의 model.save () 함수와 함께. 그것은 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);
        });
    });
    
  22. ==============================

    22.위의 글을 읽은 후, 나는이 코드를 사용하기로 결정 :

    위의 글을 읽은 후, 나는이 코드를 사용하기로 결정 :

        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 사용합니다.

  23. from https://stackoverflow.com/questions/7267102/how-do-i-update-upsert-a-document-in-mongoose by cc-by-sa and MIT license