복붙노트

[MONGODB] 몽구스 찾기 / 업데이트 하위 문서

MONGODB

몽구스 찾기 / 업데이트 하위 문서

나는 문서 폴더에 대한 다음과 같은 스키마를 가지고 :

var permissionSchema = new Schema({
    role: { type: String },
    create_folders: { type: Boolean },
    create_contents: { type: Boolean }
});

var folderSchema = new Schema({
    name: { type: string },
    permissions: [ permissionSchema ]
});

그래서, 각 페이지에 대해 나는 많은 권한을 가질 수 있습니다. 내 CMS에서 나는 모든 폴더와 권한을 표시 패널이있다. 관리자는 하나의 권한을 편집하고 저장할 수 있습니다.

나는 쉽게 하나의 권한 수정의 권한 배열로 전체 폴더의 문서를 저장할 수 있습니다. 하지만 (실제 스키마가 훨씬 더 필드가) 내가 이런 짓을 수 있도록 모든 문서를 저장하지 않습니다

savePermission: function (folderId, permission, callback) {
    Folder.findOne({ _id: folderId }, function (err, data) {
        var perm = _.findWhere(data.permissions, { _id: permission._id });                

        _.extend(perm, permission);

        data.markModified("permissions");
        data.save(callback);
    });
}

하지만 문제는 파마는 항상 정의되지 것입니다! 나는 "정적"이런 식으로 권한을 가져 오기 위해 노력했다 :

var perm = data.permissions[0];

그것은 잘 작동, 그래서 문제는 밑줄 라이브러리가 권한 배열을 조회 할 수없는 것입니다. 내가 가져온 문서의 하위 문서를 얻을 수있는 더 나은 (그리고 workgin) 방법이 추측 그래서.

어떤 생각?

P.S : 내가 루프 "를"및 [i]를 ._ ID == permission._id을 data.permissions을 확인하지만 난 똑똑한 솔루션을하고자하는 data.permission 배열의 각 항목을 확인 해결, 나는 사람이있다 알아!

해결법

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

    1.그래서 참고로, 몽구스의 기본은이 같은 배열의 데이터를 "포함"할 때 그것의 일부가 자신의 하위 문서 속성을의 당신이 각 배열 항목에 대한 _id 값을 얻을 수 있다는 것입니다. 당신은 실제로 업데이트하려는 항목의 인덱스를 결정하기 위해이 값을 사용할 수 있습니다. 이렇게하여 MongoDB의 방법은 어레이에서 "일치"위치 보유 위치 $ 연산자 변수이다 :

    그래서 참고로, 몽구스의 기본은이 같은 배열의 데이터를 "포함"할 때 그것의 일부가 자신의 하위 문서 속성을의 당신이 각 배열 항목에 대한 _id 값을 얻을 수 있다는 것입니다. 당신은 실제로 업데이트하려는 항목의 인덱스를 결정하기 위해이 값을 사용할 수 있습니다. 이렇게하여 MongoDB의 방법은 어레이에서 "일치"위치 보유 위치 $ 연산자 변수이다 :

    Folder.findOneAndUpdate(
        { "_id": folderId, "permissions._id": permission._id },
        { 
            "$set": {
                "permissions.$": permission
            }
        },
        function(err,doc) {
    
        }
    );
    

    .findOneAndUpdate () 메소드는 수정 된 문서를 반환하거나 반환 된 문서가 필요하지 않은 경우, 그렇지 않으면 당신은 방법으로 () .update를 사용할 수 있습니다. 요부가 "일치"로 업데이트 배열의 요소와 앞서 언급 한 바와 같이 위치 $과 일치하는 "을 식별"이다.

    사용자가 지정하는 요소 만이 실제로 서버에 "와이어를 통해"전송되도록 그리고 물론 당신은 $ 세트 연산자를 사용하고 있습니다. 당신은 "점 표기법"와 함께이 더 걸릴 당신이 실제로 업데이트 할 요소를 지정할 수 있습니다. 마찬가지로 :

    Folder.findOneAndUpdate(
        { "_id": folderId, "permissions._id": permission._id },
        { 
            "$set": {
                "permissions.$.role": permission.role
            }
        },
        function(err,doc) {
    
        }
    );
    

    이 MongoDB를가 제공하는 유연성은 그래서, 당신은 매우 당신이 실제로 문서를 업데이트하는 방법에서 "대상"할 수있는 곳.

    이것이 그러나 하는가하는 것은 예 : "후크 사전 저장", "확인"또는 기타로 "우회"당신이 당신의 "몽구스"스키마에 내장했을 수있는 논리이다. 은 "최적의"방법은 MongoDB의 "기능"이며 그것이 어떻게 설계되어 있기 때문이다. 그 자체가이 논리를 통해 "편리 성"래퍼로 시도 몽구스. 당신은 몇 가지 컨트롤 자신을 준비하는 경우에, 다음 업데이트는 최적의 방식으로 만들어 질 수있다.

    그래서 가능하면 이렇게 데이터를 "포함"을 유지하고 참조 모델을 사용하지 않을 수 있습니다. 그것은 당신이 동시성에 대해 걱정할 필요가 없습니다 모두 "부모"간단한 업데이트에서 "아이"항목의 원자 갱신 할 수 있습니다. 아마 당신이 처음에 MongoDB를 선택해야하는 이유 중 하나입니다.

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

    2.몽구스의 업데이트 유효성 검사 하위하기 위해, 당신은 스키마 객체로서 '부하'그것을 가지고, 다음 몽구스 자동으로 트리거 검증 및 후크.

    몽구스의 업데이트 유효성 검사 하위하기 위해, 당신은 스키마 객체로서 '부하'그것을 가지고, 다음 몽구스 자동으로 트리거 검증 및 후크.

    const userSchema = new mongoose.Schema({
      // ...
      addresses: [addressSchema],
    });
    

    사용자가 하위 문서의 배열이 있다면 몽구스 의해 제공되는 ID () 메소드를 사용하여 원하는 하나를 가져올 수있다. 그럼 당신은 개별적으로 해당 필드를 업데이트하거나 수있는 그런 다음 세트 () 메소드를 사용하여 한 번에 여러 필드를 업데이트 할 경우.

    User.findById(userId)
      .then((user) => {
        const address = user.addresses.id(addressId); // returns a matching subdocument
        address.set(req.body); // updates the address while keeping its schema       
        // address.zipCode = req.body.zipCode; // individual fields can be set directly
    
        return user.save(); // saves document with subdocuments and triggers validation
      })
      .then((user) => {
        res.send({ user });
      })
      .catch(e => res.status(400).send(e));
    

    주 당신이 정말로 사용자 문서를 찾기 위해 사용자 ID를 필요로하지 않는, 다음과 같이 일치 addressId 것을 주소 하위 문서를 가지고있는 하나를 검색하여 그것을 얻을 수 있습니다 :

    User.findOne({
      'addresses._id': addressId,
    })
    // .then() ... the same as the example above
    

    MongoDB를에서 하위 문서가 부모 문서가 저장되어있는 경우에만 저장됩니다 것을 기억하십시오.

    공식 문서에 주제에 대한 자세한 내용을 읽어 보시기 바랍니다.

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

    3.당신이 분리 수거를하지 않으려면 그냥 folderSchema에 permissionSchema을 포함.

    당신이 분리 수거를하지 않으려면 그냥 folderSchema에 permissionSchema을 포함.

    var folderSchema = new Schema({
        name: { type: string },
        permissions: [ {
            role: { type: String },
            create_folders: { type: Boolean },
            create_contents: { type: Boolean }
        } ]
    });
    

    별도의 컬렉션을해야하는 경우,이 최선의 방법입니다 :

    당신은 권한 모델을 할 수 :

    var mongoose = require('mongoose');
    var PermissionSchema = new Schema({
      role: { type: String },
      create_folders: { type: Boolean },
      create_contents: { type: Boolean }
    });
    
    module.exports = mongoose.model('Permission', PermissionSchema);
    

    그리고 허가 문서에 대한 참조를 사용하여 폴더 모델. 이 같은 다른 스키마를 참조 할 수 있습니다 :

    var mongoose = require('mongoose');
    var FolderSchema = new Schema({
      name: { type: string },
      permissions: [ { type: mongoose.Schema.Types.ObjectId, ref: 'Permission' } ]
    });
    
    module.exports = mongoose.model('Folder', FolderSchema);
    

    그리고 필드 권한을 채울 몽구스 물어 Folder.findOne (). 채우기를 ( '권한')를 호출합니다.

    이제 다음과 같은 :

    savePermission: function (folderId, permission, callback) {
        Folder.findOne({ _id: folderId }).populate('permissions').exec(function (err, data) {
            var perm = _.findWhere(data.permissions, { _id: permission._id });                
    
            _.extend(perm, permission);
    
            data.markModified("permissions");
            data.save(callback);
        });
    }
    

    합니다 (permission._id가 권한 배열에 실제로있는 경우)가 몽구스로 채워진 이후 파마 필드, 정의되지 않는다.

  4. from https://stackoverflow.com/questions/26156687/mongoose-find-update-subdocument by cc-by-sa and MIT license