mongodb에서 여러 배열 요소를 업데이트하는 방법


182

요소 배열을 보유한 Mongo 문서가 있습니다.

= XX .handled배열의 모든 객체 의 속성 을 재설정하고 싶습니다 .profile.

이 문서는 다음과 같은 형식입니다.

{
    "_id": ObjectId("4d2d8deff4e6c1d71fc29a07"),
    "user_id": "714638ba-2e08-2168-2b99-00002f3d43c0",
    "events": [{
            "handled": 1,
            "profile": 10,
            "data": "....."
        } {
            "handled": 1,
            "profile": 10,
            "data": "....."
        } {
            "handled": 1,
            "profile": 20,
            "data": "....."
        }
        ...
    ]
}

그래서 나는 다음을 시도했다.

.update({"events.profile":10},{$set:{"events.$.handled":0}},false,true)

그러나 각 문서에서 처음 일치하는 배열 요소 만 업데이트합니다 . ( $-위치 연산자에 대해 정의 된 동작입니다 .)

일치하는 배열 요소를 모두 업데이트하려면 어떻게 합니까?


2
mongodb 3.6에 서브 세트 또는 모든 배열 항목 업데이트가 추가되었습니다 : docs.mongodb.com/manual/reference/operator/update/…
Jaap

arrayFilters를 확인하고 업데이트를 효율적으로 만드는 데 사용할 쿼리를 고려하십시오. Neil Lunn의 답변을 확인하십시오 : stackoverflow.com/a/46054172/337401
Jaap

내 답변 확인
Ucdemir

답변:


111

현재 위치 연산자를 사용하여 배열의 모든 항목을 업데이트 할 수 없습니다. JIRA 참조 http://jira.mongodb.org/browse/SERVER-1243

당신의 문제를 해결하기 위해 :

  • 각 항목을 개별적으로 업데이트하거나 (events.0.handled events.1.handled ...) 또는 ...
  • 문서를 읽고 수동으로 편집 한 후 이전 문서를 대체하여 저장하십시오 ( 원자 업데이트를 확인하려면 "현재 경우 업데이트" 를 확인하십시오).

15
비슷한 문제가 있으면이 문제에 투표하십시오 -jira.mongodb.org/browse/SERVER-1243
LiorH

나는 실제로 문서를 읽고 접근하는 것을 좋아합니다. 하지만, 전체 문서 단지 REST API를 소파에 대한 쿼리 API가 없기 때문에 그 접근 방식이 더 자연스러운 것 같다, 그래서 몽고 전에 소파를 사용
아담

1
이 두 가지 방법 모두 상당히 많은 양의 메모리가 필요합니다. 검색해야 할 문서가 많고 업데이트하기 위해 모든 문서 (또는 중첩 배열)를로드해야하는 경우 ... + 또한 비동기 적으로 수행해야하는 경우 구현하기가 다소 번거 롭습니다 ...
Ixx

13
모든 기술적 어려움은 제쳐두고, MongoDB에서는이 기능을 사용할 수 없다는 것이 놀랍습니다. 이 제약 조건은 데이터베이스 스키마를 사용자 지정하지 않아도됩니다.
Sung Cho

5
Neil Lunn stackoverflow.com/a/46054172/337401 이 버전 3.6에 대해이 답변에 답변했습니다. 이것은 인기있는 질문이므로 Neil Lunn의 답변을 추천으로 받아 들인 답변을 업데이트하는 것이 좋습니다.
Jaap

72

으로 MongoDB를 3.6 버전 (MongoDB를 3.5.12에서 개발 지점에서 사용 가능한) 이제 하나의 요청에서 여러 배열 요소를 업데이트 할 수 있습니다.

이 버전에서 소개 된 필터링 된 위치$[<identifier>] 업데이트 연산자 구문을 사용합니다 .

db.collection.update(
  { "events.profile":10 },
  { "$set": { "events.$[elem].handled": 0 } },
  { "arrayFilters": [{ "elem.profile": 10 }], "multi": true }
)

"arrayFilters"에 대한 옵션에 전달로 .update()또는 .updateOne(), .updateMany(), .findOneAndUpdate()또는 .bulkWrite()방법의 지정 조건이 업데이트 문에 주어진 식별자에 일치하는. 주어진 조건과 일치하는 요소가 업데이트됩니다.

것을 주목 "multi"질문의 맥락에서 주어진 여전히이 "여러 요소를 업데이트 할"것이라고 기대에 사용하지만이 아니었고 된 것은 아니다. 여기서는 항상 최신의 API 버전에서 필수 설정으로 지정되었거나 지금 지정된대로 "다중 문서"에 적용됩니다 .updateMany().

참고 이것은 아이러니하게도, 이것은 .update()메소드 의 "옵션"인수에 지정되어 있기 때문에 일반적으로 모든 최신 릴리스 드라이버 버전과 호환됩니다.

그러나 mongo쉘에서 사실이 아닙니다 . 메소드가 구현 된 방식 ( "철도 적으로 호환성을 위해")에서는 arrayFilters인수가 이전 버전과의 "역 호환성"을 제공하기 위해 옵션을 구문 분석하는 내부 메소드로 인식 및 제거되지 않기 때문입니다. MongoDB 서버 버전 및 "레거시" .update()API 호출 구문

따라서 mongo쉘 또는 다른 "쉘 기반"제품 (특히 Robo 3T) 에서 명령을 사용 하려면 개발 지점 또는 프로덕션 릴리스 3.6 이상에서 최신 버전이 필요합니다.

또한 positional all $[]"여러 배열 요소"를 업데이트하지만 지정된 조건에 적용하지 않고 원하는 조치가있는 배열의 모든 요소에 적용되는 것도 참조하십시오 .

또한 이러한 새로운 위치 연산자가 "중첩 된"배열 구조 (어레이가 다른 배열 내에 있음)에 적용되는 방법에 대해서는 MongoDB 를 사용 하여 중첩 배열 업데이트를 참조하십시오 .

중요 -이전 버전 "에서 업그레이드 된 설치는"gogoDB 기능을 활성화하지 않았을 수 있으며 이로 인해 명령문이 실패 할 수도 있습니다. 인덱스 업그레이드와 같은 세부 정보로 업그레이드 절차를 완료 한 다음 실행해야합니다.

   db.adminCommand( { setFeatureCompatibilityVersion: "3.6" } )

또는 설치된 버전에 적용 가능한 상위 버전. 즉 "4.0", 현재 버전 4 이상입니다. 이를 통해 새로운 위치 업데이트 연산자 및 기타 기능을 사용할 수있었습니다. 당신은 또한 확인할 수 있습니다 :

   db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )

현재 설정을 되돌리려면


9
수락 된 답변은 업데이트되어야하며이 답변을 참조하십시오.
Jaap

2
무엇입니까 elem?
user1063287

1
맞습니다. RoboMongo는 arrayFilters아직 지원하지 않으므로 CLI를 통해 업데이트를 실행하십시오. stackoverflow.com/questions/48322834/…
drlff

Neil, 특히 중요한 부분에 대해 감사합니다. 정확하게 내가 필요한 것
janfabian

이 코드는 pymongo에서 ERROR를 반환합니다. 오류입니다 : raise TypeError ( "% s는 True 또는 False 여야합니다."% (옵션,)) TypeError : upsert는 True 또는 False 여야합니다.
Vagif

67

나를 위해 일한 것은 이것이었다 :

db.collection.find({ _id: ObjectId('4d2d8deff4e6c1d71fc29a07') })
  .forEach(function (doc) {
    doc.events.forEach(function (event) {
      if (event.profile === 10) {
        event.handled=0;
      }
    });
    db.collection.save(doc);
  });

몽고 초보자와 JQuery 및 친구에 익숙한 사람에게는 더 명확하다고 생각합니다.


내가 사용하고 db.posts.find({ 'permalink':permalink }).forEach( function(doc) {...난 받고 있어요Oops.. TypeError: Object # has no method 'forEach'
Squirrl

3
@Squirrl은 오래된 mongodb 버전 일 수 있습니까? 이 문서는 커서에 forEach 함수를 적용하는 방법에 대해서는 명확하지만 어떤 버전이 지원되는지 명시하지 않습니다. docs.mongodb.org/manual/reference/method/cursor.forEach
Daniel Cerecedo

@Squirrl trydb.posts.find(...).toArray().forEach(...)
marmor

우리는 이것을 사용하지 않고 이것을 할 수 없습니까 Javascript? Javascript API를 사용하지 않고 mongo 셸에서 직접이 업데이트를 수행하고 싶습니다.
Meliodas

1
이 쿼리를 java 용 mongodb 드라이버 또는 spring-data-mongodb로 작성할 수 있습니까? 고마워, kris
chiku

18

업데이트되지 않은 하위 문서가 여전히 남아있는 문서가 있는지 확인하는 while 루프를 사용하여이 작업을 수행 할 수도 있습니다. 이 방법은 업데이트의 원 자성을 유지합니다 (여기의 다른 많은 솔루션에서는 그렇지 않음).

var query = {
    events: {
        $elemMatch: {
            profile: 10,
            handled: { $ne: 0 }
        }
    }
};

while (db.yourCollection.find(query).count() > 0) {
    db.yourCollection.update(
        query,
        { $set: { "events.$.handled": 0 } },
        { multi: true }
    );
}

루프가 실행되는 횟수는 컬렉션의 모든 문서에서 profile10과 handled같고 0이 아닌 하위 문서가 발생하는 최대 횟수와 같습니다 . 따라서 컬렉션에 100 개의 문서가 있고 그 중 하나에 일치하는 3 개의 하위 query문서가 있고 다른 모든 문서에 일치하는 하위 문서가 더 적은 경우 루프가 3 번 실행됩니다.

이 방법은이 스크립트가 실행되는 동안 다른 프로세스에 의해 업데이트 될 수있는 다른 데이터를 방해 할 위험을 피합니다. 또한 클라이언트와 서버간에 전송되는 데이터의 양을 최소화합니다.


13

이것은 실제로 http://jira.mongodb.org/browse/SERVER-1243 의 오랜 문제와 관련 이 있습니다. 실제로 여러 배열이 일치하는 "모든 경우"를 지원하는 명확한 구문에 대한 여러 가지 문제가 있습니다. 녹이다. 실제로이 원본 게시물 이후에 구현 된 대량 작업같이이 문제에 대한 솔루션에서 "보조"된 방법이 이미 있습니다.

단일 업데이트 명령문에서 일치하는 단일 배열 요소를 두 개 이상 업데이트 할 수는 없으므로 "다중"업데이트를 수행하더라도 업데이트 할 수있는 모든 것은 해당 단일 문서의 각 문서에 대해 배열에서 하나의 계산 된 요소 일뿐입니다. 성명서.

현재 가능한 최선의 해결책은 일치하는 모든 문서를 찾아 루프하고 대량 업데이트를 처리하여 최소한 단일 응답으로 단일 작업으로 많은 작업을 보낼 수 있도록하는 것입니다. 선택적으로 .aggregate()검색 결과에 반환 된 배열 내용을 업데이트 선택 조건과 일치하는 배열 내용으로 줄이는 데 사용할 수 있습니다 .

db.collection.aggregate([
    { "$match": { "events.handled": 1 } },
    { "$project": {
        "events": {
            "$setDifference": [
               { "$map": {
                   "input": "$events",
                   "as": "event",
                   "in": {
                       "$cond": [
                           { "$eq": [ "$$event.handled", 1 ] },
                           "$$el",
                           false
                       ]
                   }
               }},
               [false]
            ]
        }
    }}
]).forEach(function(doc) {
    doc.events.forEach(function(event) {
        bulk.find({ "_id": doc._id, "events.handled": 1  }).updateOne({
            "$set": { "events.$.handled": 0 }
        });
        count++;

        if ( count % 1000 == 0 ) {
            bulk.execute();
            bulk = db.collection.initializeOrderedBulkOp();
        }
    });
});

if ( count % 1000 != 0 )
    bulk.execute();

.aggregate()배열의 각 요소에 대한 모든 컨텐츠의 "고유"식별자는 "고유"요소 자체를 형성하고있을 때 일부가 작동 할 것이다. 이는 일치를 위해 배열을 처리하는 데 사용 된 작업 에서 반환 된 값 $setDifference을 필터링하는 데 사용되는 "set"연산자 때문입니다 .false$map

배열 내용에 고유 한 요소가없는 경우 다음을 사용하여 대체 방법을 시도 할 수 있습니다 $redact.

db.collection.aggregate([
    { "$match": { "events.handled": 1 } },
    { "$redact": {
        "$cond": {
            "if": {
                "$eq": [ { "$ifNull": [ "$handled", 1 ] }, 1 ]
            },
            "then": "$$DESCEND",
            "else": "$$PRUNE"
        }
    }}
])

"처리 된"필드가 실제로 다른 문서 레벨에 존재하는 필드 인 경우 예상치 않은 결과를 얻을 수 있지만 해당 필드가 하나의 문서 위치에만 나타나고 동등하게 일치하는 것이 좋습니다.

글을 쓰는 현재의 릴리스 (3.1 이후 몽고 DB) $filter는 더 간단한 작업을 할 것입니다 :

db.collection.aggregate([
    { "$match": { "events.handled": 1 } },
    { "$project": {
        "events": {
            "$filter": {
                "input": "$events",
                "as": "event",
                "cond": { "$eq": [ "$$event.handled", 1 ] }
            }
        }
    }}
])

그리고 지원하는 모든 릴리스 .aggregate()는 다음과 같은 접근 방식을 사용할 수 $unwind있지만 해당 연산자를 사용하면 파이프 라인의 배열 확장으로 인해 가장 효율적인 접근 방식이됩니다.

db.collection.aggregate([
    { "$match": { "events.handled": 1 } },
    { "$unwind": "$events" },
    { "$match": { "events.handled": 1 } },
    { "$group": {
        "_id": "$_id",
        "events": { "$push": "$events" }
    }}        
])

MongoDB 버전이 집계 출력에서 ​​"커서"를 지원하는 모든 경우에, 이는 접근법을 선택하고 대량 업데이트 명령문을 처리하기 위해 표시된 동일한 코드 블록으로 결과를 반복하는 것입니다. 집계 출력의 대량 작업 및 "커서"는 동일한 버전 (MongoDB 2.6)으로 도입되므로 일반적으로 처리를 위해 함께 작동합니다.

이전 버전에서도 .find()커서를 반환하고 배열 요소가 .update()반복에 일치하는 횟수만큼 명령문 실행을 필터링하는 것이 가장 좋습니다 .

db.collection.find({ "events.handled": 1 }).forEach(function(doc){ 
    doc.events.filter(function(event){ return event.handled == 1 }).forEach(function(event){
        db.collection.update({ "_id": doc._id },{ "$set": { "events.$.handled": 0 }});
    });
});

"다중"업데이트를 수행하기로 결정했거나 일치하는 각 문서에 대해 여러 업데이트를 처리하는 것보다 궁극적으로 더 효율적인 것으로 판단되는 경우 항상 가능한 최대 배열 일치 수를 결정하고 "다중"업데이트 만 실행할 수 있습니다. 기본적으로 업데이트 할 문서가 더 이상 없을 때까지.

MongoDB 2.4 및 2.2 버전에 대한 올바른 접근 방법을 사용 .aggregate()하여이 값을 찾을 수도 있습니다 .

var result = db.collection.aggregate([
    { "$match": { "events.handled": 1 } },
    { "$unwind": "$events" },
    { "$match": { "events.handled": 1 } },
    { "$group": {
        "_id": "$_id",
        "count": { "$sum": 1 }
    }},
    { "$group": {
        "_id": null,
        "count": { "$max": "$count" }
    }}
]);

var max = result.result[0].count;

while ( max-- ) {
    db.collection.update({ "events.handled": 1},{ "$set": { "events.$.handled": 0 }},{ "multi": true })
}

어떤 경우 든 업데이트 내에서 원하지 않는 사항이 있습니다 .

  1. 배열을 "한 번에"업데이트하지 마십시오. 코드에서 전체 배열 내용을 업데이트 한 다음 $set각 문서의 전체 배열 만 업데이트하는 것이 더 효율적일 수 있습니다 . 처리 속도가 더 빠를 수 있지만 배열 내용을 읽은 후 업데이트가 수행 된 이후로 변경되지 않았다는 보장은 없습니다. 비록 $set단지 올바른 데이터 인 "생각", 따라서, 판독과 기록 사이에서 발생하는 변경을 덮어 가능성 것과 배열을 업데이트 여전히 원자 연산자이다.

  2. 업데이트 할 인덱스 값을 계산하지 마십시오 . "원샷"접근 방식과 유사한 경우 해당 위치 0및 위치 등 2을 업데이트하여 다음과 같은 최종 결과 명령문을 업데이트하고 코딩하는 요소입니다.

    { "$set": {
        "events.0.handled": 0,
        "events.2.handled": 0
    }}

    여기서도 문제는 문서를 읽을 때 발견 된 색인 값이 업데이트시 배열의 색인 값과 동일한 "가정"입니다. 순서를 변경하는 방식으로 배열에 새 항목을 추가하면 해당 위치가 더 이상 유효하지 않으며 잘못된 항목이 실제로 업데이트됩니다.

따라서 여러 개의 일치하는 배열 요소를 단일 업데이트 명령문에서 처리 할 수 ​​있도록 합리적인 구문이 결정될 때까지 기본 접근 방식은 일치하는 각 배열 요소를 개별 명령문 (이상적으로는 Bulk)으로 업데이트하거나 본질적으로 최대 배열 요소를 해결하는 것입니다. 더 이상 수정 된 결과가 반환되지 않을 때까지 업데이트하거나 계속 업데이트합니다. 어쨌든, 일치하는 배열 요소에 대한 위치$ 업데이트를 "항상"처리해야 합니다. 명령문마다 하나의 요소 만 업데이트하는 경우에도 마찬가지입니다.

대량 작업은 실제로 "다중 작업"으로 작동하는 작업을 처리하기위한 "일반화 된"솔루션이며, 동일한 값으로 여러 배열 요소를 업데이트하는 것보다 더 많은 응용 프로그램이 있으므로 물론 구현되었습니다. 이미이 문제를 해결하는 가장 좋은 방법입니다.


8

나는 이것이 여전히 몽고에서 다루어지지 않은 것에 놀랐다. 하위 배열을 다룰 때 전반적인 몽고는 좋지 않은 것 같습니다. 예를 들어 하위 배열을 계산할 수 없습니다.

Javier의 첫 번째 솔루션을 사용했습니다. 배열을 이벤트로 읽은 다음 반복하여 set exp를 빌드하십시오.

var set = {}, i, l;
for(i=0,l=events.length;i<l;i++) {
  if(events[i].profile == 10) {
    set['events.' + i + '.handled'] = 0;
  }
}

.update(objId, {$set:set});

조건부 테스트를위한 콜백을 사용하여 함수로 추상화 할 수 있습니다.


감사합니다! 이 기능이 여전히 기본적으로 지원되지 않는다고 믿을 수 없습니다! 이것을 사용하여 하위 배열의 모든 항목을 증가시키고 다른 사람들이 읽기를 위해 모든 항목을 업데이트하려면 if 문을 제거하십시오.
Zaheer

9
이것은 안전한 해결책이 아닙니다. 업데이트를 실행하는 동안 레코드가 추가되면 데이터가 손상됩니다.
Merc

4

나는 C # 3.6의 최신 드라이버를 사용하여 이것에 대한 해결책을 찾고 있었고 결국 해결 된 수정 사항이 있습니다. 여기서 중요한 것은 "$ []"를 사용 하는 것으로, MongoDB에 따르면 버전 3.6부터는 새로운 것입니다. https://docs.mongodb.com/manual/reference/operator/update/positional-all/#up을 참조 하십시오. 자세한 내용은 S [] 를 참조하십시오.

코드는 다음과 같습니다.

{
   var filter = Builders<Scene>.Filter.Where(i => i.ID != null);
   var update = Builders<Scene>.Update.Unset("area.$[].discoveredBy");
   var result = collection.UpdateMany(filter, update, new UpdateOptions { IsUpsert = true});
}

자세한 내용은 MongoDB C # 드라이버를 사용하여 모든 문서에서 배열 요소 제거를 참조하십시오.


4

스레드는 매우 오래되었지만 여기에 답을 찾고 새로운 솔루션을 제공했습니다.

MongoDB 버전 3.6 이상에서는 위치 연산자를 사용하여 배열의 모든 항목을 업데이트 할 수 있습니다. 공식 문서를 참조 하십시오 .

다음 질문은 여기에서 묻는 질문에 효과적입니다. Java-MongoDB 드라이버로도 확인했으며 성공적으로 작동합니다.

.update(   // or updateMany directly, removing the flag for 'multi'
   {"events.profile":10},
   {$set:{"events.$[].handled":0}},  // notice the empty brackets after '$' opearor
   false,
   true
)

이것이 나와 같은 누군가를 돕기를 바랍니다.


1

나는 다음과 그 작동을 시도했다.

.update({'events.profile': 10}, { '$set': {'events.$.handled': 0 }},{ safe: true, multi:true }, callback function);

// nodejs의 경우 콜백 함수


이 코드는 배열에서 처음 일치하는 항목을 업데이트합니다. 잘못된 답변.
Hamlett

v2.6에서 작동합니다. 이전 버전 일 수 있습니까? 다음의 문서 년대 docs.mongodb.com/manual/reference/method/db.collection.update/...은
Jialin Zou는

1

MongoDB의 모든 요소를 ​​업데이트 할 수 있습니다

db.collectioname.updateOne(
{ "key": /vikas/i },
{ $set: { 
 "arr.$[].status" : "completed"
} }
)

"arr"배열에서 모든 "status"값을 "completed"로 업데이트합니다.

하나의 문서 만

db.collectioname.updateOne(
 { key:"someunique", "arr.key": "myuniq" },
 { $set: { 
   "arr.$.status" : "completed", 
   "arr.$.msgs":  {
                "result" : ""
        }
   
 } }
)

그러나 하나가 아니며 배열의 모든 문서를 업데이트하지 않으려면 요소를 통해 if 블록 내부를 반복해야합니다.

db.collectioname.find({findCriteria })
  .forEach(function (doc) {
    doc.arr.forEach(function (singlearr) {
      if (singlearr check) {
        singlearr.handled =0
      }
    });
    db.collection.save(doc);
  });

0

실제로, 저장 명령은 Document 클래스의 인스턴스에만 있습니다. 많은 방법과 속성이 있습니다. 따라서 lean () 함수를 사용하여 작업 부하를 줄일 수 있습니다. 여기를 참조하십시오. https://hashnode.com/post/why-are-mongoose-mongodb-odm-lean-queries-faster-than-normal-queries-cillvawhq0062kj53asxoyn7j

저장 기능의 또 다른 문제는 동시에 다중 저장과 충돌하는 데이터를 만드는 것입니다. Model.Update 는 데이터를 일관되게 만듭니다. 따라서 문서 배열에서 여러 항목을 업데이트합니다. 익숙한 프로그래밍 언어를 사용하고 이와 같은 것을 시도하십시오. 저는 몽구스를 사용합니다.

User.findOne({'_id': '4d2d8deff4e6c1d71fc29a07'}).lean().exec()
  .then(usr =>{
    if(!usr)  return
    usr.events.forEach( e => {
      if(e && e.profile==10 ) e.handled = 0
    })
    User.findOneAndUpdate(
      {'_id': '4d2d8deff4e6c1d71fc29a07'},
      {$set: {events: usr.events}},
      {new: true}
    ).lean().exec().then(updatedUsr => console.log(updatedUsr))
})

0

$ [] 연산자는 모든 중첩 배열을 선택합니다. '$ []'로 모든 배열 항목을 업데이트 할 수 있습니다.

.update({"events.profile":10},{$set:{"events.$[].handled":0}},false,true)

참고


여기 끝에 "false, true"를 포함시키는 이유를 설명해 주시겠습니까? 설명서에서 찾을 수 없습니다.
garson

모든 위치 연산자 $[] 는 지정된 배열의 모든 필드를 업데이트합니다. 작동하는 것은 $[identifier]지정된 조건과 일치하는 배열 필드의 연산자 인 필터링 된 위치 연산자 입니다. 참조 arrayFilters : docs.mongodb.com/manual/release-notes/3.6/#arrayfiltersdocs.mongodb.com/manual/reference/operator/update/…
Lawrence Eagles

0

이 쓰레드에서 $ [] 사용이 잘못되었음을 시사하는 답변이 있습니다.

db.collection.update(
   {"events.profile":10},
   {$set:{"events.$[].handled":0}},
   {multi:true}
)

위의 코드는 "프로파일"값에 관계없이 "이벤트"배열의 모든 요소에 대해 "처리됨"을 0으로 업데이트합니다. 쿼리 {"events.profile":10}는 배열의 문서가 아닌 전체 문서 만 필터링합니다. 이 상황에서 그것을 사용하는 필수입니다 $[elem]arrayFilters닐 룬의 대답이 정확한지 있도록 배열 항목의 조건을 지정할 수 있습니다.


0

mongo db의 여러 문서에서 배열 필드를 업데이트하십시오.

mongoDb에서 배열 요소를 업데이트하려면 많은 쿼리 업데이트와 함께 $ pull 또는 $ push를 사용하십시오.

Notification.updateMany(
    { "_id": { $in: req.body.notificationIds } },
    {
        $pull: { "receiversId": req.body.userId }
    }, function (err) {
        if (err) {
            res.status(500).json({ "msg": err });
        } else {
            res.status(200).json({
                "msg": "Notification Deleted Successfully."
            });
        }
    });

0

첫째 : 위치 연산자를 사용했기 때문에 코드가 작동하지 않았습니다. $ 배열에서 업데이트 할 요소 만 식별하고 배열에서 해당 위치를 명시 적으로 지정하지 않는 를 하지 않았습니다.

필요한 것은 필터링 된 위치 연산자 $[<identifier>]입니다. 배열 필터 조건과 일치하는 모든 요소를 ​​업데이트합니다.

해결책:

db.collection.update({"events.profile":10}, { $set: { "events.$[elem].handled" : 0 } },
   {
     multi: true,
     arrayFilters: [ { "elem.profile": 10 } ]
})

여기 mongodb doc을 방문하십시오.

코드가하는 일 :

  1. {"events.profile":10} 컬렉션을 필터링하고 필터와 일치하는 문서를 반환

  2. $set업데이트 운영자 : 수정 문서의 필드를 일치 그것은에 역할을합니다.

  3. {multi:true}.update()필터와 일치하는 모든 문서 를 수정하므로 다음과 같이 작동합니다.updateMany()

  4. { "events.$[elem].handled" : 0 } and arrayFilters: [ { "elem.profile": 10 } ] 이 기술은 arrayFilters와 함께 필터링 된 위치 배열을 사용합니다. 여기서 필터링 된 위치 배열 $[elem]은 배열 필터에 지정된 조건과 일치하는 배열 필드의 모든 요소에 대한 자리 표시 자 역할을합니다.

배열 필터

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.