mongoDB에서 업데이트를 사용한 집계
유사한 구조화된 문서가 많은 컬렉션을 가지고 있는데, 문서 중 두 개는 다음과 같습니다.
입력:
{
"_id": ObjectId("525c22348771ebd7b179add8"),
"cust_id": "A1234",
"score": 500,
"status": "A"
"clear": "No"
}
{
"_id": ObjectId("525c22348771ebd7b179add9"),
"cust_id": "A1234",
"score": 1600,
"status": "B"
"clear": "No"
}
으로 적으로clear
는 모든문가입니다."No"
,
요청: 동일한 모든 문서의 점수를 추가해야 합니다.cust_id
그들이 소속되어 있다면,status
"A"
그리고.status
"B"
에 약에만.score
을 초과하는2000
그러면 나는 업데이트를 해야 합니다.clear
다리탓으에 대한 ."Yes"
한 동한모문대해서의 cust_id
.
예상 출력:
{
"_id": ObjectId("525c22348771ebd7b179add8"),
"cust_id": "A1234",
"score": 500,
"status": "A"
"clear": "Yes"
}
{
"_id": ObjectId("525c22348771ebd7b179add9"),
"cust_id": "A1234",
"score": 1600,
"status": "B"
"clear": "Yes"
}
예, 1600+500 = 2100 및 2100 > 2000 때문입니다.
내 접근 방식: 집계 함수로만 합계를 얻을 수 있었지만 업데이트에 실패했습니다.
db.aggregation.aggregate([
{$match: {
$or: [
{status: 'A'},
{status: 'B'}
]
}},
{$group: {
_id: '$cust_id',
total: {$sum: '$score'}
}},
{$match: {
total: {$gt: 2000}
}}
])
어떻게 진행해야 하는지 제안 부탁드립니다.
많은 어려움을 겪은 후에, 몽고 껍질을 실험해 본 저는 마침내 제 질문에 대한 해결책을 얻었습니다.
Psudo 코드:
# To get the list of customer whose score is greater than 2000
cust_to_clear=db.col.aggregate(
{$match:{$or:[{status:'A'},{status:'B'}]}},
{$group:{_id:'$cust_id',total:{$sum:'$score'}}},
{$match:{total:{$gt:500}}})
# To loop through the result fetched from above code and update the clear
cust_to_clear.result.forEach
(
function(x)
{
db.col.update({cust_id:x._id},{$set:{clear:'Yes'}},{multi:true});
}
)
동일한 질문에 대해 다른 해결책이 있다면 코멘트를 부탁드립니다.
Mongo 4.2에서는 이제 집계 파이프라인을 사용한 업데이트를 사용하여 이 작업을 수행할 수 있습니다.예제 2에는 조건부 업데이트를 수행하는 방법이 나와 있습니다.
db.runCommand(
{
update: "students",
updates: [
{
q: { },
u: [
{ $set: { average : { $avg: "$tests" } } },
{ $set: { grade: { $switch: {
branches: [
{ case: { $gte: [ "$average", 90 ] }, then: "A" },
{ case: { $gte: [ "$average", 80 ] }, then: "B" },
{ case: { $gte: [ "$average", 70 ] }, then: "C" },
{ case: { $gte: [ "$average", 60 ] }, then: "D" }
],
default: "F"
} } } }
],
multi: true
}
],
ordered: false,
writeConcern: { w: "majority", wtimeout: 5000 }
}
)
다른 예:
db.c.update({}, [
{$set:{a:{$cond:{
if: {}, // some condition
then:{} , // val1
else: {} // val2 or "$$REMOVE" to not set the field or "$a" to leave existing value
}}}}
]);
이 작업은 두 단계로 수행해야 합니다.
- 식별합니다.
cust_id
) 이상인 점이상 200점 이상인 경우 - 각각에 이한각고대해설정에객러를 합니다.
clear
Yes
당신은 이미 첫 번째 부분에 대한 좋은 해결책을 가지고 있습니다.두 번째 부분은 데이터베이스에 대한 별도의 호출로 구현되어야 합니다.
Psudo 코드:
# Get list of customers using the aggregation framework
cust_to_clear = db.col.aggregate(
{$match:{$or:[{status:'A'},{status:'B'}]}},
{$group:{_id:'$cust_id', total:{$sum:'$score'}}},
{$match:{total:{$gt:2000}}}
)
# Loop over customers and update "clear" to "yes"
for customer in cust_to_clear:
id = customer[_id]
db.col.update(
{"_id": id},
{"$set": {"clear": "Yes"}}
)
모든 고객에 대해 데이터베이스 통화를 해야 하기 때문에 이상적이지 않습니다.이런 종류의 작업을 자주 수행해야 하는 경우 스키마를 수정하여 각 문서에 총 점수를 포함시킬 수 있습니다. (이는 응용 프로그램에서 유지 관리해야 합니다.)이 경우 다음 명령을 사용하여 업데이트를 수행할 수 있습니다.
db.col.update(
{"total_score": {"$gt": 2000}},
{"$set": {"clear": "Yes"}},
{"multi": true}
)
단답:데이터베이스 쿼리가 반복되지 않도록 하려면 끝에 $merge를 추가하고 컬렉션을 다음과 같이 지정합니다.
db.aggregation.aggregate([
{$match: {
$or: [
{status: 'A'},
{status: 'B'}
]
}},
{$group: {
_id: '$cust_id',
total: {$sum: '$score'}
}},
{$match: {
total: {$gt: 2000}
}},
{ $merge: "<collection name here>"}
])
정교함:현재 솔루션은 데이터베이스 쿼리를 순환하고 있으며, 이는 시간 효율이 좋지 않고 코드도 훨씬 많습니다.Mitar의 답변은 집계를 통한 업데이트가 아니라 Mongo의 업데이트 내에서 집계를 이용한 =>의 반대입니다.이러한 방식으로 작업을 수행하는 데 있어 전문가가 무엇인지 궁금하다면 설명서에 명시된 대로 일부로만 제한되는 대신 모든 집계 파이프라인을 사용할 수 있습니다.
다음은 Mongo의 업데이트에서 작동하지 않는 집계의 예입니다.
db.getCollection('foo').aggregate([
{ $addFields: {
testField: {
$in: [ "someValueInArray", '$arrayFieldInFoo']
}
}},
{ $merge : "foo" }]
)
이렇게 하면 "someValueInArray"가 "arrayFieldInFoo"에 있으면 true가 되고 그렇지 않으면 false가 되는 새 테스트 필드가 업데이트된 컬렉션이 출력됩니다.현재 Mongo.update에서는 $in을 업데이트 Aggregate 내에서 사용할 수 없으므로 이 작업을 수행할 수 없습니다.
업데이트: 전체 컬렉션을 $out으로 업데이트하는 경우에만 $out이 작동하므로 $out에서 $merge로 변경되었습니다.$165는 집계가 문서와 일치하는 경우에만 재정의됩니다(더 안전한 경우).
MongoDB 2.6.에서는 동일한 명령으로 집계 쿼리의 출력을 작성할 수 있습니다.
자세한 내용은 여기에서 확인하십시오. http://docs.mongodb.org/master/reference/operator/aggregation/out/
제가 찾은 솔루션은 "$out"을 사용하는 것입니다.
*) 예: 필드 추가:
db.socios.aggregate(
[
{
$lookup: {
from: 'cuotas',
localField: 'num_socio',
foreignField: 'num_socio',
as: 'cuotas'
}
},
{
$addFields: { codigo_interno: 1001 }
},
{
$out: 'socios' //Collection to modify
}
]
)
*) 예: 필드 수정:
db.socios.aggregate(
[
{
$lookup: {
from: 'cuotas',
localField: 'num_socio',
foreignField: 'num_socio',
as: 'cuotas'
}
},
{
$set: { codigo_interno: 1001 }
},
{
$out: 'socios' //Collection to modify
}
]
)
언급URL : https://stackoverflow.com/questions/19384871/aggregation-with-update-in-mongodb
'sourcecode' 카테고리의 다른 글
TypeScript 유형 무시 대소문자 (0) | 2023.07.07 |
---|---|
"메모리가 8바이트 정렬"이라는 것은 무엇을 의미합니까? (0) | 2023.07.07 |
부트스트랩 양식에 두 필드를 나란히 표시 (0) | 2023.07.07 |
커밋, 커밋 및 푸시, 커밋 및 동기화의 차이점 (0) | 2023.07.07 |
스프링 부팅 및 최대 절전 모드: DDL 인쇄/로그 (0) | 2023.07.07 |