2016-09-13 2 views
3

내 응용 프로그램은 원격 서버에서 데이터를 받고 ReplaceOne을 호출하여 새 키를 삽입하거나 기존 키를 Upsert = true으로 대체합니다. (키는 *으로 익명 처리됩니다.) 코드는 단일 스레드에서만 실행됩니다.ReplaceOne이 중복 키 예외를 throw합니다

그러나, 때때로 다음과 같은 오류와 응용 프로그램의 충돌 :

Unhandled Exception: MongoDB.Driver.MongoWriteException: A write operation resulted in an error.        
    E11000 duplicate key error collection: ****.orders index: _id_ dup key: { : "****-********-********-************" } ---> MongoDB.Driver.MongoBulkWriteException`1[MongoDB.Bson.BsonDocument]: A bulk write operation resulted in one or more errors.                            
    E11000 duplicate key error collection: ****.orders index: _id_ dup key: { : "****-********-********-************" }                             
    at MongoDB.Driver.MongoCollectionImpl`1.BulkWrite(IEnumerable`1 requests, BulkWriteOptions options, CancellationToken cancellationToken)                            
    at MongoDB.Driver.MongoCollectionBase`1.ReplaceOne(FilterDefinition`1 filter, TDocument replacement, UpdateOptions options, CancellationToken cancellationToken)                      
    --- End of inner exception stack trace ---                     
    at MongoDB.Driver.MongoCollectionBase`1.ReplaceOne(FilterDefinition`1 filter, TDocument replacement, UpdateOptions options, CancellationToken cancellationToken)                      
    at Dashboard.Backend.AccountMonitor.ProcessOrder(OrderField& order)              
    at Dashboard.Backend.AccountMonitor.OnRtnOrder(Object sender, OrderField& order)           
    at XAPI.Callback.XApi._OnRtnOrder(IntPtr ptr1, Int32 size1)                
    at XAPI.Callback.XApi.OnRespone(Byte type, IntPtr pApi1, IntPtr pApi2, Double double1, Double double2, IntPtr ptr1, Int32 size1, IntPtr ptr2, Int32 size2, IntPtr ptr3, Int32 size3)                 
Aborted (core dumped) 

내 질문에, 왜 내가 Upsert = true 옵션 ReplaceOne을 사용할 때 DUP 키를 가질 수 있습니다?

응용 프로그램은 다음과 같은 환경과 런타임에서 일하고 :

.NET Command Line Tools (1.0.0-preview2-003121) 

Product Information: 
Version:   1.0.0-preview2-003121 
Commit SHA-1 hash: 1e9d529bc5 

Runtime Environment: 
OS Name:  ubuntu 
OS Version: 16.04 
OS Platform: Linux 
RID:   ubuntu.16.04-x64 

그리고 MongoDB.Driver 2.3.0-rc1합니다.

답변

0

정보가 충분하지 않지만 시나리오가 다음과 같을 수 있습니다. 서버로부터 데이터를 수신하면 replaceOne 명령이 어떤 레코드와도 일치하지 않으며 새로운 것을 삽입하려고 시도하지만 아마도 고유하고 이미 콜렉션에 존재하는 문서. 업데이트하거나 삽입하기 전에 데이터를 검토하고 변경하십시오.

2

Upsert는 필터 쿼리를 기반으로 작동합니다. 필터 쿼리가 일치하지 않으면 문서를 삽입하려고 시도합니다.

필터 쿼리가 문서를 찾으면 문서를 대체합니다.

귀하의 경우 삽입/업데이트 중 어느 경우에도 진행될 수 있습니다. 시나리오를 분석하려면 데이터를 확인하십시오.

삽입 시나리오 : - _id는 필터 기준에없는 경우

실제 _id가 upsert에 의해 자동으로 생성됩니다. 따라서 _id는 고유성 문제를 생성해서는 안됩니다. 다른 필드가 고유 인덱스의 일부인 경우 고유성 문제가 발생합니다.

시나리오를 바꾸기 : -

당신이 고유 인덱스가 정의해야 업데이트하려고하는 필드. 컬렉션 및 해당 속성에 대한 색인을 확인하십시오. 이 일에

Optional. When true, replaceOne() either: Inserts the document from the replacement parameter if no document matches the filter. Replaces the document that matches the filter with the replacement document.

To avoid multiple upserts, ensure that the query fields are uniquely indexed.

Defaults to false.

MongoDB will add the _id field to the replacement document if it is not specified in either the filter or replacement documents. If _id is present in both, the values must be equal.

+0

내 필터는'_id'하고있다 정확히 같은'_id' 교체/upsert 할 문서에 있습니다. –

+0

고유 인덱스가 정의되어 있는지 여부를 업데이트하려는 필드를 확인 했습니까? – notionquest

+0

컬렉션에는 고유 인덱스로 '_id' 만 있습니다. –

0

내가 할 수있는 공동 서명 :

public async Task ReplaceOneAsync(T item) 
    { 
     try 
     { 
      await _mongoCollection.ReplaceOneAsync(x => x.Id.Equals(item.Id), item, new UpdateOptions { IsUpsert = true }); 
     } 
     catch (MongoWriteException) 
     { 
      var count = await _mongoCollection.CountAsync(x => x.Id.Equals(item.Id)); // lands here - and count == 1 !!! 
     } 
    } 
관련 문제