복붙노트

[MONGODB] MongoDB를 : upsert 하위 문서

MONGODB

MongoDB를 : upsert 하위 문서

나는 bars.name에 고유 인덱스와 같은 무언가를 보이는 문서가 :

{이름 : '갑'바 : [{이름 'qux'somefield 1}]}

. {: '갑', 'bars.name': 'qux'이름} 및 $ 세트 : { '바 $ somefield..': 2} 또는 새 하위 문서를 만들 나도 업데이트 할 수있는 하위 문서를 원하는 아래 {이름 : 'foo는'} {: 'qux', somefield 2 명}에.

그것은 upsert로 하나의 쿼리를 사용하여이 작업을 수행 할 수 있는가, 아니면 별도의 두 사람 문제에 것인가?

관련 : 'upsert를'포함 된 문서 (키와 하위 문서 식별자를 가지고 스키마를 변경 제안하지만,이 2 년 전부터이며, 더 나은 솔루션은 이제이 있는지 궁금하네요.)

해결법

  1. ==============================

    1.아니 정말 설명 너무 아마 이것에 더 나은 솔루션, 없다.

    아니 정말 설명 너무 아마 이것에 더 나은 솔루션, 없다.

    당신이 보여 같은 구조를 가지고 장소에서 문서가 있다고 가정 :

    { 
      "name": "foo", 
      "bars": [{ 
           "name": "qux", 
           "somefield": 1 
      }] 
    }
    

    이 같은 업데이 트를 할 경우

    db.foo.update(
        { "name": "foo", "bars.name": "qux" },
        { "$set": { "bars.$.somefield": 2 } },
        { "upsert": true }
    )
    

    일치하는 문서가 발견 되었기 때문에 모든 괜찮습니다. 하지만 "bars.name"의 값을 변경하는 경우 :

    db.foo.update(
        { "name": "foo", "bars.name": "xyz" },
        { "$set": { "bars.$.somefield": 2 } },
        { "upsert": true }
    )
    

    그럼 당신은 실패를 얻을 것이다. 정말 여기에 변경된 유일한 것은 MongoDB를 2.6 및 오류 위가 좀 더 간결하다는 것이다 :

    WriteResult({
        "nMatched" : 0,
        "nUpserted" : 0,
        "nModified" : 0,
        "writeError" : {
            "code" : 16836,
            "errmsg" : "The positional operator did not find the match needed from the query. Unexpanded update: bars.$.somefield"
        }
    })
    

    즉 더 나은 어떤 방법으로,하지만 당신은 정말 어쨌든 "upsert"를 원하지 않는다. 당신이 원하는 것은 "이름이"현재 존재하지 않는 배열에 요소를 추가합니다.

    그래서 당신이 정말로 원하는 것은 모든 문서가 영향을받은 경우 볼 수있는 "upsert"플래그없이 업데이트 시도에서 "결과"입니다 :

    db.foo.update(
        { "name": "foo", "bars.name": "xyz" },
        { "$set": { "bars.$.somefield": 2 } }
    )
    

    응답 항복 :

    WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
    

    수정 된 문서는 다음 0을 때 그래서 당신은 당신이 다음 업데이트를 발행 할 알고 :

    db.foo.update(
        { "name": "foo" },
        { "$push": { "bars": {
            "name": "xyz",
            "somefield": 2
        }}
    )
    

    정말 정확히 당신이 원하는 것을 할 수있는 다른 방법이 없습니다. 배열에 추가 엄격 작업의 "설정"유형하지 않습니다, 당신은 그래서 당신이 할 수있는 "폭포"를 업데이트 할 것을 요청, 거기에 "대량 업데이트"기능과 결합 $ addToSet을 사용할 수 없습니다.

    당신이 결과를 확인하거나 그렇지 않으면 전체 문서를 읽고 갱신 여부를 코드에 새로운 배열 요소 삽입 확인에 동의해야처럼이 경우 보인다.

  2. ==============================

    2.당신은 스키마를 조금 변경 등과 같은 구조를 갖는 마음을 해달라고하면 :

    당신은 스키마를 조금 변경 등과 같은 구조를 갖는 마음을 해달라고하면 :

    { "name": "foo", "bars": { "qux": { "somefield": 1 },
                               "xyz": { "somefield": 2 },
                      }
    }
    

    당신은 한 번에 당신의 작업을 수행 할 수 있습니다. 완전성에 포함 된 문서에 'upsert을'투자 의견 유지

  3. ==============================

    3.업데이트가 업데이트되는 기록에 대한 참조에 의존하는 경우에 할 수있는 방법이 없다 (예를 들어, 업데이트 X => X + 1). 당신의 삽입이 거부되는 경우 때문에 때문에 중복에 중복 확인하여 해결할 수없는 경쟁 조건에서 2 개의 분리 (다음 삽입 설정) 명령 결과를 발행하는 것은, 당신이 당신의 갱신 (의 효과를 잃게 예를 들어, X는 않을 것 위의 예)에서 적절히 증가 될 수있다. MongoDB를가 포함 된 문서를 특정 응용 프로그램에 대한 MongoDB를에 큰 끌기 구현할 수 있기 때문에,이 기능을 추가 한 경우 좋은 것입니다.

    업데이트가 업데이트되는 기록에 대한 참조에 의존하는 경우에 할 수있는 방법이 없다 (예를 들어, 업데이트 X => X + 1). 당신의 삽입이 거부되는 경우 때문에 때문에 중복에 중복 확인하여 해결할 수없는 경쟁 조건에서 2 개의 분리 (다음 삽입 설정) 명령 결과를 발행하는 것은, 당신이 당신의 갱신 (의 효과를 잃게 예를 들어, X는 않을 것 위의 예)에서 적절히 증가 될 수있다. MongoDB를가 포함 된 문서를 특정 응용 프로그램에 대한 MongoDB를에 큰 끌기 구현할 수 있기 때문에,이 기능을 추가 한 경우 좋은 것입니다.

  4. ==============================

    4.이 두 개의 쿼리에서 그것을 할 수있는 방법은 -하지만 그것은 bulkWrite에서 작업을 계속 것입니다.

    이 두 개의 쿼리에서 그것을 할 수있는 방법은 -하지만 그것은 bulkWrite에서 작업을 계속 것입니다.

    내 경우는 배치 할 수없는에서 가장 큰 끊기 때문 관련이있다. 이 솔루션으로, 당신은 당신이 필요한 경우 대량 작업을 수행 할 수 있습니다 첫 번째 쿼리의 결과를 수집 할 필요가 없습니다.

    여기 예를 들어 실행하는 두 개의 연속 쿼리는 다음과 같습니다

    // Update subdocument if existing
    collection.updateMany({
        name: 'foo', 'bars.name': 'qux' 
    }, {
        $set: { 
            'bars.$.somefield': 2 
        }
    })
    // Insert subdocument otherwise
    collection.updateMany({
        name: 'foo', $not: {'bars.name': 'qux' }
    }, {
        $push: { 
            bars: {
                somefield: 2, name: 'qux'
            }
        }
    })
    

    이것은 또한 여러 응용 프로그램이 동시에 데이터베이스에 작성하는 경우 손상된 데이터 / 경쟁 조건을 가지고 있지의 추가 혜택을했다. 두 막대 결말 위험하지 않습니다 : {somefield : 2, 이름을 'qux'} 문서의 하위 문서를 두 개의 응용 프로그램이 동시에 같은 쿼리를 실행합니다.

  5. from https://stackoverflow.com/questions/23470658/mongodb-upsert-sub-document by cc-by-sa and MIT license