복붙노트

[MONGODB] 하위 문서와 nodejs / 몽구스의 부분 갱신

MONGODB

하위 문서와 nodejs / 몽구스의 부분 갱신

그것은 하나 몽구스와 이동에 (하위) 문서의 여러 속성을 설정할 수 있습니까? 내가 할 노력하고있어의 예 :

하자 내가이 스키마가 있다고 가정 :

var subSchema = new Schema({
    someField: String,
    someOtherField: String
});

var parentSchema = new Schema({
    fieldOne: String,
    subDocs: [subSchema]
})

그럼 내가 할 싶습니다 :

exports.updateMyDocument = function(req, res) {
    var parentDoc = req.parentDoc; // The parent document. Set by parameter resolver.
    var document = req.myDoc; // Sub document of parent. Set by parameter resolver.
    var partialUpdate = req.body; // updated fields sent as json and parsed by body parser
    // I know that the statement below doesn't work, it's just an example of what I would like to do.
    // Updating only the fields supplied in "partialUpdate" on the document
    document.update(partialUpdate); 
    parentDoc.save(function(err) {
        if(err) {
            res.send(500);
            return;
        }
        res.send(204);
    }); 
};

일반적으로, 나는 이것이 $ 세트 연산자를 사용하여 얻을 수 있지만, 내 문제는이 예에서 해당 문서가 parentDoc의 하위 문서 (임베디드 스키마)입니다. 내가하려고 할 때 그래서

Parent.update({_id: parentDoc._id, "subDocs._id": document._id}, 
    {$set: {"subDocs.$" : partialUpdate}}, 
    function(err, numAffected) {});

그것은 subDocs._id에 의해 식별 된 하위 문서 인스턴스를 교체했다. 현재 내가 수동으로 만 필드를 설정하여 "해결"했다,하지만 난이 일을 더 나은 방법을 기대했다.

해결법

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

    1.프로그래밍 점 표기법을 사용하여 바로 해당 필드 업데이트 할 partialUpdate의 분야에 따라 $ 세트 객체를 구축 :

    프로그래밍 점 표기법을 사용하여 바로 해당 필드 업데이트 할 partialUpdate의 분야에 따라 $ 세트 객체를 구축 :

    var set = {};
    for (var field in partialUpdate) {
      set['subDocs.$.' + field] = partialUpdate[field];
    }
    Parent.update({_id: parentDoc._id, "subDocs._id": document._id}, 
        {$set: set}, 
        function(err, numAffected) {});
    
  2. ==============================

    2.나는 REST 응용 프로그램에서 다른 완료했습니다.

    나는 REST 응용 프로그램에서 다른 완료했습니다.

    첫째,이 경로가 :

    router.put('/:id/:resource/:resourceId', function(req, res, next) {
        // this method is only for Array of resources.
        updateSet(req.params.id, req.params.resource, req, res, next);
    });
    

    상기 updateSet () 메소드

    function updateSet(id, resource, req, res, next) {
        var data = req.body;
        var resourceId = req.params.resourceId;
    
        Collection.findById(id, function(err, collection) {
            if (err) {
                rest.response(req, res, err);
            } else {
                var subdoc = collection[resource].id(resourceId);
    
                // set the data for each key
                _.each(data, function(d, k) {
                  subdoc[k] = d;
                });
    
                collection.save(function (err, docs) {
                  rest.response(req, res, err, docs);
                });
            }
        });
    }
    

    화려한 부분은이 하위 문서의 스키마를 정의하는 경우 몽구스가 데이터의 유효성을 검사합니다. 이 코드는 배열이다 문서의 모든 자원에 대해 유효합니다. 나는 편의를 위해 내 모든 데이터를 보여주는 아니지만,이 상황을 확인하고 적절하게 응답 오류를 처리하는 것이 좋습니다.

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

    3.당신은 할당하거나 포함 된 문서를 확장 할 수 있습니다.

    당신은 할당하거나 포함 된 문서를 확장 할 수 있습니다.

        Doc.findOne({ _id: docId })
        .then(function (doc) {
          if (null === doc) {
            throw new Error('Document not found');
          }
    
          return doc.embeded.id(ObjectId(embeddedId));
        })
        .then(function(embeddedDoc) {
          if (null === embeddedDoc) {
            throw new Error('Embedded document not found');
          }
    
          Object.assign(embeddedDoc, updateData));
          return embeddedDoc.parent().save();
        })
        .catch(function (err) {
          //Do something
        });
    

    그리고이 경우에 당신은 _id가 할당되지 않도록 슈어해야한다.

  4. ==============================

    4.나는 $ 세트 객체를 사용하지 않고 약간 다른 방식으로이 문제를 처리. 나의 접근 방식은 Guilherme의 비슷하지만 한 가지 차이점은 내 응용 프로그램 전체를 다시 쉽게 사용할 수 있도록 내가 정적 기능에 나의 방법을 포장 것입니다. 예 아래.

    나는 $ 세트 객체를 사용하지 않고 약간 다른 방식으로이 문제를 처리. 나의 접근 방식은 Guilherme의 비슷하지만 한 가지 차이점은 내 응용 프로그램 전체를 다시 쉽게 사용할 수 있도록 내가 정적 기능에 나의 방법을 포장 것입니다. 예 아래.

    CollectionSchema.js 서버 모델에서.

    collectionSchema.statics.decrementsubdocScoreById = function decreasesubdoc (collectionId, subdocId, callback) {
      this.findById(collectionId, function(err, collection) {
        if (err) console.log("error finding collection");
        else {
          var subdoc = collection.subdocs.filter(function (subdoc) {
            return subdoc._id.equals(subdocId);
          })[0];
    
          subdoc.score -= 1;
    
          collection.save(callback);
        }
      });
    };
    

    에서 서버 컨트롤러

    Collection.decrementsubdocScoreById(collectionId, subdocId, function  (err, data) {
      handleError(err);
      doStuffWith(data);
    });
    
  5. from https://stackoverflow.com/questions/15874750/partial-update-of-a-subdocument-with-nodejs-mongoose by cc-by-sa and MIT license