2017-09-17 2 views
1

MongoDB에서 SubItem 배열로 항목을 기록합니다. SubItems를 추가하거나 업데이트 할 때 먼저 FindItem을 입력 한 다음 을 SubItems의 배열에 추가하고 전체를 Item으로 바꿉니다. 이것은 SubItems을 일괄 적으로 삽입하기 전까지 "훌륭함"을 나타 냈습니다.안전하게 MongoDB에 하위 문서를 삽입하거나 업데이트하십시오.

내 문제는 찾기 및 업데이트가 하나의 원자 적 연산이 아니며 결과가 SubItems을 잃어 버리고 있다는 것입니다.

내가 .NET MongoDB.Driver 내 저장 방법을 사용하고있어 다음과 같습니다 : 여기

public Task Save(string itemId, SubItem subItem) 
{ 
    var itemFilter = Builders<Item>.Filter.Eq(v => v.Id, itemId); 
    var collection = _db.GetCollection<Item>("Items"); 

    var item = await collection.Find(itemFilter).SingleOrDefaultAsync(); 

    item.SubItems.Add(subItem); 
    collection.ReplaceOneAsync(itemFilter, item, new UpdateOptions() { IsUpsert = true }).Wait(); 
    return Task.FromResult(0); 
} 

내 데이터 모델입니다 :

public class Item 
{ 
    public string Id { get; set; } 
    public List<SubItem> SubItems { get; set; } 
} 

public class SubItem 
{ 
    public string Id { get; set; } 
} 

삽입하는 방법 또는 업데이트가 있습니까 한 번의 작업으로 SubItem을 사용하면 문서를 동시에 업데이트하려고하는 여러 프로세스가 있어도 전체 Item 문서를 일관되게 유지할 수 있습니까?

+0

"업서 트"및 어레이는 일반적으로 매우 잘 혼합되지 않습니다. 일반적으로 배열의 항목이 있는지 여러 작업 (일반적으로 대량)으로 "테스트"한 다음 새 항목을 "밀어 넣거나"있는 곳에 "업데이트"합니다. [ "$ addToSet'] (https://docs.mongodb.com/manual/reference/operator/update/addToSet/)로 사례를"다소 "단순화 할 수 있습니다."if "배열 내용이 단순히 값이거나"single "재산. 그러나 둘 이상의 속성이있는 경우 "고유성"은 해당 상황에서 해당 속성의 조합을 의미하며 대신 "테스트"방법으로 대체됩니다. –

+0

"upsert"문제는 이러한 업데이트가 배열 내의 요소 존재를 "테스트"해야하는 경우입니다. "모든"음수 결과는 실제 의도가 배열의 "추가"일 때 "업서 트"가 항상 발생한다는 것을 의미합니다. 새로운 것보다는 기존의 문서. 따라서 실제로 사용하는 실제 프로세스는 의도 한 패턴에 따라 다릅니다. 진정으로 "upserts"를 원하고 배열에 여러 속성을 원한다면 실제로는 "다중 작업"을 대신 수행해야합니다. –

답변

1

AddToSet 메서드를 살펴 보았습니까?이 기능을 바꾸기 대신 업데이트 기능과 함께 사용하면 원 자성을보다 잘 제어 할 수 있습니다.

var updateBuilder = Builders<Item>.Update.AddToSet(items => items.SubItems, new SubItem()); 

collection.UpdateOne(itemFilter, updateBuilder); 

귀하의 경우에도 마찬가지입니다.

public Task Save(string itemId, SubItem subItem) 
    { 
     var itemFilter = Builders<Item>.Filter.Eq(v => v.Id, itemId); 
     var collection = _db.GetCollection<Item>("Items"); 

     var updateBuilder = Builders<Item>.Update.AddToSet(items => items.SubItems, subItem); 

     collection.UpdateOneAsync(itemFilter, updateBuilder, new UpdateOptions() { IsUpsert = true }).Wait(); 
    } 
관련 문제