2016-09-13 60 views
3

我的應用程序從遠程服務器接收數據並調用ReplaceOne要麼插入新的或與Upsert = true給定的鍵替換現有文件。 (密鑰是由匿名與*)代碼只運行在單個線程。ReplaceOne引發重複鍵異常

但是,有時,應用程序崩潰,出現以下錯誤:

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) 

我的問題是,爲什麼它可以當我使用ReplaceOneUpsert = true選項有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。所以,_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'和UPSERT /替換具有完全相同的'_id'文檔。 –

+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 !!! 
     } 
    }