2017-01-16 1 views
2

내가 아는 한 mongodb은 Dictionary을 객체로 알고 있으며 배열과 관련된 모든 작업을 수행 할 수 없습니다. 나는 연재를 바꾸었고 다양한 형태의 사전 연재를 시도했다. 그러나 기회는 없습니다.
그래서 필드 (사전) (전체)를 메모리에로드하고 업데이트 한 다음 다시 mongodb로 설정합니다.
upsert 사전에 mongodb와 C# 드라이버가 있습니까?Upsert Dictionary in MongoDb


내 문서 형식 :

public class Site 
    { 
     public string Id { get; set; } 
     //[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfDocuments)] 
     public Dictionary<string,string> Properties { get; set; } 
    } 

내 업데이트 작업 :

public ServiceResult UpdateProperties(string id, Dictionary<string,string> properties) 
     { 
      var baseList = Collection.Find(m => m.Id == id) 
       .Project(s => s.Properties) 
       .FirstOrDefault(); 

      if (baseList == null) 
      { 
       baseList = properties; 
      } 
      else 
      { 
       baseList.Upsert(properties); //update,insert dic by new one 
      } 

      var filter = Builders<Site>.Filter 
       .Eq(m => m.Id, id); 

      var update = Builders<Site>.Update 
       .Set(m => m.Properties, baseList); 

      try 
      { 
       Collection.UpdateOne(filter, update); 

       return ServiceResult.Okay(Messages.ItemUpdated); 

      } 
      catch (Exception ex) 
      { 
       return ServiceResult.Exception(ex); 
      }  
     } 

난 정말 당신이 제공 할 수있는 모든 도움을 주셔서 감사합니다.


동음 :

public static class DictionaryExtensions 
    { 
     public static void Upsert<TKey, TValue>(this Dictionary<TKey, TValue> source, 
              Dictionary<TKey, TValue> newOne) 
     { 
      foreach (var item in newOne) 
      { 
       source[item.Key] = item.Value; 
      } 
     } 
    } 

답변

1

당신은/삽입을 업데이트 할 모든 속성을 통해 이동하여 각 속성을 위해 그것을 할 수있다 : 여러으로, 대답의

UpdateDefinition<Site> upsert = null; 
if (properties.Any()) 
{ 
    var firstprop = properties.First(); 
    upsert = Builders<Site>.Update.Set(nameof(Site.Properties) + "." + firstprop.Key, 
           firstprop.Value); 

    foreach (var updateVal in properties.Skip(1)) 
    { 
     upsert = upsert.Set(nameof(Site.Properties) + "." + updateVal.Key, 
              updateVal.Value); 
    } 

    collection.UpdateOne(r => r.Id == "YourId", upsert, 
               new UpdateOptions { IsUpsert = true }); 
} 

이전 버전 업데이트 :

foreach (var updateVal in properties) 
{ 
    collection.UpdateOne(r => r.Id == "YourId", 
     Builders<Site>.Update.Set(nameof(Site.Properties)+ "." + updateVal.Key, 
            updateVal.Value), 
            new UpdateOptions { IsUpsert = true}); 
} 

새로운 키/값을 추가하거나 기존 항목을 업데이트하기 만하면 아무 것도 제거되지 않습니다.

+0

작동합니다. 정말 좋은 포인트 맨. 다중 연결 (업데이트)을 피하기위한 제안이 있는지 보도록하겠습니다. 지금까지 이것은 나를 위해 받아 들여진 대답입니다. – Soren

+0

대답을 업데이트했습니다.이 업데이트는 한 번만 실행됩니다. –

+0

은 매력처럼 작동합니다. 귀하의 시간과 배려에 감사드립니다. – Soren