MongoDB: 배열 요소의 속성에 대한 고유 인덱스
이와 유사한 구조를 가지고 있습니다.
class Cat {
int id;
List<Kitten> kittens;
}
class Kitten {
int id;
}
사용자가 동일한 ID의 고양이를 둘 이상 사용하여 고양이를 만들지 못하도록 합니다.다음과 같이 인덱스를 만들어 보았습니다.
db.Cats.ensureIndex({'id': 1, 'kittens.id': 1}, {unique:true})
하지만 제가 잘못된 형식의 고양이를 삽입하려고 하면, Mongo는 그것을 받아들입니다.
제가 뭔가를 놓쳤나요? 이게 가능할까요?
고유 인덱스는 서로 다른 문서에 고유성만 적용하므로 중복 키 오류가 발생할 수 있습니다.
db.cats.insert( { id: 123, kittens: [ { id: 456 } ] } )
db.cats.insert( { id: 123, kittens: [ { id: 456 } ] } )
그러나 이는 허용됩니다.
db.cats.insert( { id: 123, kittens: [ { id: 456 }, { id: 456 } ] } )
Mongo 레벨에서 당신이 필요로 하는 제약을 적용할 방법이 있는지 모르겠습니다, 혹시 업데이트를 삽입할 때 애플리케이션 로직에서 확인할 수 있는 것이 아닐까요?
배열 필드에서 개별 값의 고유성 보장
위의 예 외에도 MongoDB에는 배열 필드에 새 개체/값을 추가할 때 값/객체가 아직 존재하지 않는 경우에만 업데이트를 수행하도록 하는 기능이 있습니다.
따라서 다음과 같은 문서가 있으면 다음과 같습니다.
{ _id: 123, kittens: [456] }
이는 허용됩니다.
db.cats.update({_id:123}, {$push: {kittens:456}})
결과적으로
{ _id: 123, kittens: [456, 456] }
그러나 $addToSet 함수($push가 아닌)를 사용하면 값을 추가하기 전에 값이 이미 있는지 확인합니다.그럼, 다음과 같이 시작합니다.
{ _id: 123, kittens: [456] }
실행 중:
db.cats.update({_id:123}, {$addToSet: {kittens:456}})
아무 효과도 없을 것입니다.
따라서, 긴 이야기의 짧고 고유한 제약 조건은 배열 필드의 값 항목 내에서 고유성을 검증하지 않습니다. 단지 두 문서가 색인 필드에서 동일한 값을 가질 수 없다는 것입니다.
배열 특성에 고유한 삽입이 있습니다.다음 명령은 기본적으로 아기 고양이의 고유성을 보장하는 동시에 삽입합니다(123이 있는 개체가 아직 존재하지 않는 경우 업퍼트가 사용자를 위해 작성됨).
db.cats.update(
{ id: 123 },
{ $addToSet: {kittens: { $each: [ 456, 456] }}, $set: {'otherfields': 'extraval', "field2": "value2"}},
{ upsert: true}
)
객체의 결과 값은 다음과 같습니다.
{
"id": 123,
"kittens": [456],
"otherfields": "extraval",
"field2": "value2"
}
여기서 중요한 것은 mongodb 개체 배열에 동일한 ID 또는 고유하게 처리해야 하는 일부 다른 필드를 가진 항목만 존재하지 않도록 하는 것입니다.그런 다음, 이와 같은 간단한 쿼리는 다음을 사용하여 업데이트하기에 충분합니다.$addToSet
.
죄송합니다. 저는 자바 몽고 드라이버 버전 4.0.3을 사용하는 몽고 셸 전문가가 아닙니다.
collection = database.getCollection("cat", Cat.class);
UpdateResult result = collection.updateOne(and(eq("Id", 1), nin("kittens.id", newKittenId)), addToSet("kittens", new Kitten("newKittenId")));
여기에 사용된 쿼리는 일치 쿼리에 추가 조건을 추가했습니다. 여기서 cat.id 은 1이고 새 KittenId는 아직 이전에 추가된 고양이가 소유하지 않습니다.따라서 고양이의 ID가 발견되었지만 새 고양이 ID를 가져간 고양이가 없으면 쿼리가 진행되고 새 고양이를 추가하여 고양이의 고양이를 업데이트합니다.그러나 새로운 KittenId가 고양이 중 한 마리에 의해 찍혔다면, 그것은 단순히 업데이트 결과를 카운트 없이 반환하고 수정된 필드는 반환하지 않습니다(아무 일도 일어나지 않습니다).
참고: 이것은 kitten.id 의 고유 제약 조건을 보장하지 않으며, mongo DB는 문서의 객체 배열에 대한 고유성을 지원하지 않으며, addToSet은 객체 배열에서 중복된 항목을 실제로 처리하지 않습니다. 단, 객체가 데이터베이스에 있는 내용의 100% 복제본인 경우는 제외합니다.addToSet
.
문서 검증기를 사용하여 수행할 수 있는 해결 방법이 있습니다.
다음은 "a"가 배열이고 "a" 하위 문서 필드 "b" 값이 고유해야 하는 검증자의 예입니다.이렇게 하면 컬렉션이 비어 있거나 이미 규칙을 준수하는 것으로 가정합니다.
> db.runCommand({collMod:"coll", validator: {$expr:{$eq:[{$size:"$a.b"},{$size:{$setUnion:"$a.b"}}]}}})
/* test it */
> db.coll.insert({a:[{b:1}]}) /* success */
> db.coll.update({},{ '$push' : { 'a':{b:1}}})
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
원본 게시물에서 이 솔루션에 대한 자세한 정보 보기
이 경우 사용자 지정 Mongoose 유효성 검사 방법을 작성할 수 있습니다.사후 검증에 연결할 수 있습니다.Mongoose에는 유효성 검사가 있으며 유효성 검사 전(사전) 또는 후(사후)에 후크를 구현할 수 있습니다.이 경우 사후 검증을 사용하여 어레이가 유효한지 확인할 수 있습니다.그런 다음 배열에 중복이 없는지 확인하십시오.세부 정보에 따라 효율성을 개선할 수 있습니다.예를 들어 '_id'만 있으면 JS include 함수를 사용할 수 있습니다.
catSchema.post('validate',function(next) {
return new Promise((resolve,reject) => {
for(var i = 0; i < this.kittens.length; i++) {
let kitten = this.kittens[i];
for(var p = 0; p < this.kittens.length; p++) {
if (p == i) {
continue;
}
if (kitten._id == this.kittens[p]._id) {
return reject('Duplicate Kitten Ids not allowed');
}
}
}
return resolve();
});
});
저는 오류를 지정하는 것이 더 쉽기 때문에 검증에 약속을 사용하는 것을 좋아합니다.
언급URL : https://stackoverflow.com/questions/6743849/mongodb-unique-index-on-array-elements-property
'programing' 카테고리의 다른 글
WEB-INF 폴더가 Spring Boot 응용 프로그램에 생성되지 않습니까? (0) | 2023.07.06 |
---|---|
TypeScript에서 생성자를 데코레이터로 올바르게 감싸는 방법 (0) | 2023.07.06 |
Mac용 Excel의 배열 수식 (0) | 2023.07.06 |
서버에서 모든 데이터베이스 삭제 (0) | 2023.07.06 |
중괄호와 와일드카드를 사용한 Oracle 텍스트 이스케이프 (0) | 2023.07.06 |