UFO ET IT

Mongoose 하위 문서 찾기/업데이트

ufoet 2023. 5. 13. 20:33
반응형

Mongoose 하위 문서 찾기/업데이트

문서 폴더에 대한 스키마는 다음과 같습니다.

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

문제는 언더스코어 라이브러리가 권한 배열을 쿼리할 수 없다는 것입니다.따라서 가져온 문서의 하위 문서를 가져올 수 있는 더 나은 방법이 있을 것입니다.

감 잡히는 게 없어요?

추신: "for" 루프를 사용하여 data.permission 배열의 각 항목을 확인하고 data.permissions[i]를 확인하는 문제를 해결했습니다._id == 권한입니다._그렇지만 좀 더 현명한 해결책이 필요해요, 한 가지가 있다는 걸 알아요!

를 " "mongoose"가 ._id각 배열 항목에 대한 값을 자체 하위 항목 속성의 일부로 지정할 수 있습니다.실제로 이 값을 사용하여 업데이트할 항목의 인덱스를 확인할 수 있습니다.MongoDB 방법은 배열에서 "일치된" 위치를 유지하는 위치 연산자 변수입니다.

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

    }
);

이 메서드는 수정된 문서를 반환합니다. 그렇지 않으면 사용할 수 있습니다..update()만약 당신이 서류를 반환할 필요가 없다면 방법으로.주요 부분은 업데이트할 배열의 요소를 "일치"하는 것과 앞서 언급한 위치와 일치하는 "식별"하는 것입니다.

그런 다음 사용자는 지정한 구성요소만 실제로 "무선을 통해" 서버로 전송되도록 연산자를 사용합니다."도트 표기법"을 사용하여 업데이트할 요소를 지정할 수 있습니다.다음과 같이:

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

    }
);

이것이 MongoDB가 제공하는 유연성으로, 실제로 문서를 업데이트하는 방법에 대해 매우 "대상"이 될 수 있습니다.

그러나 이렇게 하면 "검증" 또는 기타 "저장 전 후크"와 같이 "mongoose" 스키마에 내장된 모든 논리를 "바이패스"할 수 있습니다.이는 "최적"인 방법이 MongoDB "기능"이며 설계 방법이기 때문입니다.Mongoose 자체는 이 논리에 대해 "편리한" 포장지가 되려고 노력합니다.그러나 직접 제어할 준비가 되어 있다면 업데이트를 가장 최적의 방법으로 수행할 수 있습니다.

따라서 가능한 경우 데이터를 "내장"된 상태로 유지하고 참조된 모델을 사용하지 마십시오.동시성에 대해 걱정할 필요가 없는 단순 업데이트에서 "상위" 및 "하위" 항목을 모두 원자적으로 업데이트할 수 있습니다.아마도 당신이 애초에 MongoDB를 선택했어야 하는 이유 중 하나일 것입니다.

Mongoose에서 업데이트할 때 하위 문서의 유효성을 검사하려면 Schema 개체로 '로드'해야 합니다. 그러면 Mongoose는 자동으로 유효성 검사와 후크를 트리거합니다.

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

하위 문서의 배열이 있는 경우, 다음과 같이 원하는 문서를 가져올 수 있습니다.id()Mongoose에서 제공하는 메서드입니다.그런 다음 필드를 개별적으로 업데이트하거나 여러 필드를 동시에 업데이트하려면set()방법.

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

실제로 필요한 것은 아닙니다.userId사용자 문서를 찾으려면 주소 하위 문서와 일치하는 주소 하위 문서를 검색하여 문서를 가져올 수 있습니다.addressId다음과 같이:

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

MongoDB에서는 상위 문서가 저장될 때만 하위 문서가 저장됩니다.

공식 문서의 항목에 대한 자세한 내용은 다음을 참조하십시오.

별도의 수집을 원하지 않는 경우 Schema 권한을 Schema 폴더에 포함하기만 하면 됩니다.

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().populate('permissions')mongoose에게 필드 권한을 채우도록 요청합니다.

자, 다음과 같습니다.

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

perm필드가 정의되지 않습니다(권한이 있는 경우)._id는 실제로 권한 배열에 있습니다. 왜냐하면 Mongoose에 의해 채워졌기 때문입니다.

그냥 해보세요

let doc = await Folder.findOneAndUpdate(
    { "_id": folderId, "permissions._id": permission._id },
    { "permissions.$": permission},
);

언급URL : https://stackoverflow.com/questions/26156687/mongoose-find-update-subdocument

반응형