MongoDB - 배열에 개체 업데이트 또는 삽입
다음 컬렉션을 가지고 있습니다.
{
"_id" : ObjectId("57315ba4846dd82425ca2408"),
"myarray" : [
{
userId : ObjectId("570ca5e48dbe673802c2d035"),
point : 5
},
{
userId : ObjectId("613ca5e48dbe673802c2d521"),
point : 2
},
]
}
이것들은 나의 질문들입니다.
나는 밀고 싶습니다.myarray
한다면userId
존재하지 않습니다. 에 추가해야 합니다.myarray
.한다면userId
존재합니다. 포인트로 업데이트해야 합니다.
나는 이걸 발견했어.
db.collection.update({
_id : ObjectId("57315ba4846dd82425ca2408"),
"myarray.userId" : ObjectId("570ca5e48dbe673802c2d035")
}, {
$set: { "myarray.$.point": 10 }
})
하지만 만약에userId
존재하지 않고, 아무 일도 일어나지 않습니다.
그리고.
db.collection.update({
_id : ObjectId("57315ba4846dd82425ca2408")
}, {
$push: {
"myarray": {
userId: ObjectId("570ca5e48dbe673802c2d035"),
point: 10
}
}
})
하지만 만약에userId
개체가 이미 있습니다. 개체가 다시 푸시됩니다.
MongoDB에서 이것을 하는 가장 좋은 방법은 무엇입니까?
사용해 보세요.
db.collection.update(
{ _id : ObjectId("57315ba4846dd82425ca2408")},
{ $pull: {"myarray.userId": ObjectId("570ca5e48dbe673802c2d035")}}
)
db.collection.update(
{ _id : ObjectId("57315ba4846dd82425ca2408")},
{ $push: {"myarray": {
userId:ObjectId("570ca5e48dbe673802c2d035"),
point: 10
}}
)
설명: 첫 번째 문장에서$pull
를 사용하여 요소를 제거합니다.userId= ObjectId("570ca5e48dbe673802c2d035")
문서의 배열에서._id = ObjectId("57315ba4846dd82425ca2408")
두 번째에.$push
이 개체를 삽입합니다.{ userId:ObjectId("570ca5e48dbe673802c2d035"), point: 10 }
같은 배열로
플라잉 피셔가 인정한 답은 기존 기록이 먼저 삭제된 다음 다시 밀린다는 것입니다.
더 안전한 접근법(상식)은 레코드를 먼저 업데이트하고 일치하는 내용이 없으면 다음과 같이 삽입하는 것입니다.
// first try to overwrite existing value
var result = db.collection.update(
{
_id : ObjectId("57315ba4846dd82425ca2408"),
"myarray.userId": ObjectId("570ca5e48dbe673802c2d035")
},
{
$set: {"myarray.$.point": {point: 10}}
}
);
// you probably need to modify the following if-statement to some async callback
// checking depending on your server-side code and mongodb-driver
if(!result.nMatched)
{
// record not found, so create a new entry
// this can be done using $addToSet:
db.collection.update(
{
_id: ObjectId("57315ba4846dd82425ca2408")
},
{
$addToSet: {
myarray: {
userId: ObjectId("570ca5e48dbe673802c2d035"),
point: 10
}
}
}
);
// OR (the equivalent) using $push:
db.collection.update(
{
_id: ObjectId("57315ba4846dd82425ca2408"),
"myarray.userId": {$ne: ObjectId("570ca5e48dbe673802c2d035"}}
},
{
$push: {
myarray: {
userId: ObjectId("570ca5e48dbe673802c2d035"),
point: 10
}
}
}
);
}
이는 또한 (상식적으로, 테스트되지 않은) 성능 향상을 제공해야 하며, 대부분의 경우 레코드가 이미 존재하는 경우 첫 번째 쿼리만 실행됩니다.
MongoDB v4.2에서 시작하는 집계 파이프라인으로 문서 업데이트라는 옵션이 있습니다.
- 상태를 확인합니다.
$cond
한다면userId
안에myarray.userId
그렇지 않으면. - 그렇다면
$map
반복하여myarray
배열 및 상태 확인userId
일치시킨 후 다음을 사용하여 새 문서와 병합합니다.$mergeObjects
- 만약 그렇지 않다면
$concatArrays
새로운 목적을 달성하기 위해 그리고.myarray
let _id = ObjectId("57315ba4846dd82425ca2408");
let updateDoc = {
userId: ObjectId("570ca5e48dbe673802c2d035"),
point: 10
};
db.collection.update(
{ _id: _id },
[{
$set: {
myarray: {
$cond: [
{ $in: [updateDoc.userId, "$myarray.userId"] },
{
$map: {
input: "$myarray",
in: {
$mergeObjects: [
"$$this",
{
$cond: [
{ $eq: ["$$this.userId", updateDoc.userId] },
updateDoc,
{}
]
}
]
}
}
},
{ $concatArrays: ["$myarray", [updateDoc]] }
]
}
}
}]
)
안타깝게도 내장형 어레이에서는 "업서트" 작업을 수행할 수 없습니다.연산자가 존재하지 않기 때문에 단일 문에서는 연산자를 사용할 수 없습니다.따라서 원하는 작업을 수행하려면 두 가지 업데이트 작업을 수행해야 합니다.또한 원하는 결과를 얻기 위해서는 이 두 업데이트의 적용 순서가 중요합니다.
단일 원자 쿼리에 기반한 솔루션을 찾지 못했습니다.대신 두 개의 쿼리 시퀀스를 기반으로 하는 세 가지 방법이 있습니다.
항상
$pull
(어레이에서 항목을 제거하려면), 그런 다음$push
(업데이트된 항목을 배열에 추가)db.collection.update( { _id : ObjectId("57315ba4846dd82425ca2408")}, { $pull: {"myarray.userId": ObjectId("570ca5e48dbe673802c2d035")}} ) db.collection.update( { _id : ObjectId("57315ba4846dd82425ca2408")}, { $push: { "myarray": { userId:ObjectId("570ca5e48dbe673802c2d035"), point: 10 } } } )
노력하다
$set
(존재하는 경우 배열의 항목을 업데이트함), 결과를 가져와 업데이트 작업이 성공했는지 확인합니다.$push
needs(항목 삽입)var result = db.collection.update( { _id : ObjectId("57315ba4846dd82425ca2408"), "myarray.userId": ObjectId("570ca5e48dbe673802c2d035") }, { $set: {"myarray.$.point": {point: 10}} } ); if(!result.nMatched){ db.collection.update({_id: ObjectId("57315ba4846dd82425ca2408")}, { $addToSet: { myarray: { userId: ObjectId("570ca5e48dbe673802c2d035"), point: 10 } } );
항상
$addToSet
(존재하지 않는 경우 항목을 추가하려면),$set
배열의 항목을 업데이트합니다.db.collection.update({_id: ObjectId("57315ba4846dd82425ca2408")}, myarray: { $not: { $elemMatch: {userId: ObjectId("570ca5e48dbe673802c2d035")} } } }, { $addToSet : { myarray: { userId: ObjectId("570ca5e48dbe673802c2d035"), point: 10 } } }, { multi: false, upsert: false}); db.collection.update({ _id: ObjectId("57315ba4846dd82425ca2408"), "myArray.userId": ObjectId("570ca5e48dbe673802c2d035") }, { $set : { myArray.$.point: 10 } }, { multi: false, upsert: false});
첫 번째와 두 번째 방법은 안전하지 않으므로 두 개의 동시 요청을 방지하려면 트랜잭션을 설정해야 합니다.push
중복 항목을 생성하는 동일한 항목입니다.
세 번째 방법이 더 안전합니다.그$addToSet
항목이 없는 경우에만 추가하고, 그렇지 않으면 아무 일도 일어나지 않습니다.두 개의 동시 요청의 경우, 그 중 하나만 누락된 항목을 배열에 추가합니다.
애그리게이션 파이프라인을 통해 가능한 솔루션:
db.collection.update(
{ _id },
[
{
$set: {
myarray: { $filter: {
input: '$myarray',
as: 'myarray',
cond: { $ne: ['$$myarray.userId', ObjectId('570ca5e48dbe673802c2d035')] },
} },
},
},
{
$set: {
myarray: {
$concatArrays: [
'$myarray',
[{ userId: ObjectId('570ca5e48dbe673802c2d035'), point: 10 },
],
],
},
},
},
],
);
2단계를 사용합니다.
myarray
if (= 다음경요제거소우의▁(▁if)userId
- 필터 처리된 캣콘여
myarray
새로운 요소 포함;
어레이에 값을 업데이트하거나 삽입할 때 사용합니다.
db의 개체
key:name,
key1:name1,
arr:[
{
val:1,
val2:1
}
]
쿼리
var query = {
$inc:{
"arr.0.val": 2,
"arr.0.val2": 2
}
}
.updateOne( { "key": name }, query, { upsert: true }
key:name,
key1:name1,
arr:[
{
val:3,
val2:3
}
]
MongoDB 3.6에서는 이제 배열의 요소를 뒤집을 수 있습니다.
어레이 업데이트와 생성은 하나의 쿼리 아래에서 혼합되지 않습니다. 원자성에 대해 많이 신경 쓴다면 다음과 같은 해결책이 있습니다.
스키마를 다음으로 정규화합니다.
{
"_id" : ObjectId("57315ba4846dd82425ca2408"),
userId : ObjectId("570ca5e48dbe673802c2d035"),
point : 5
}
.for.each/.update현재 mongosh CLI에서 사용하는 한 가지 방법을 사용하여 이러한 작업을 수행할 수 있습니다.각각의 .for에서 언급한 모든 조건을 설정할 수 있습니다.
각/.업데이트에 대한 .의 예하나:
let medications = db.medications.aggregate([
{$match: {patient_id: {$exists: true}}}
]).toArray();
medications.forEach(med => {
try {
db.patients.updateOne({patient_id: med.patient_id},
{$push: {medications: med}}
)
} catch {
console.log("Didn't find match for patient_id. Could not add this med to a patient.")
}
})
이것이 가장 "MongoDB 방식"은 아닐 수도 있지만, 확실히 작동하고 각 .for에서 작업을 수행할 수 있는 자바스크립트의 자유를 제공합니다.
언급URL : https://stackoverflow.com/questions/37427610/mongodb-update-or-insert-object-in-array
'itsource' 카테고리의 다른 글
Oracle SQL - 하나의 문이 있는 테이블에 여러 행을 삽입하시겠습니까? (0) | 2023.06.21 |
---|---|
봄에 @Bean 방법에서 선택적 매개변수(의존성)를 정의하는 방법은 무엇입니까? (0) | 2023.06.21 |
Visual Studio에서 푸시되지 않은 나가는 커밋을 제거하는 방법은 무엇입니까? (0) | 2023.06.21 |
Vuejs 3은 하위 구성 요소에서 상위 구성 요소로 이벤트를 내보냅니다. (0) | 2023.06.21 |
src/**/*.graphql 포인터에 대한 GraphQL 유형 정의를 찾을 수 없습니다. (0) | 2023.06.21 |