MongoDB - C# insert, update, delete

기본 추가

  • 클래스 맵핑으로 새 도큐먼트 추가
var newData = new DBBasic()
{
    _id = "test01",
    Level = 1,
    Exp = 0,
    Money = 1000,
    Costume = new List<int>(Enumerable.Repeat(0, 12)),
};

// Basic 컬렉션에 추가한다
var collection = Common.GetDBCollection<DBBasic>("Basic");
await collection.InsertOneAsync(newData);
  • BsonDocument를 사용하여 추가.
Int64 money = 1000;
var Costume = new List<int>(Enumerable.Repeat(0,12));
var document = new BsonDocument { { "_id", userID }, { "Level", 1 }, { "Exp", 0 }, { "Money", money }, { "Costume", new BsonArray(Costume) } };

var collection = GetDBCollection<BsonDocument>("Basic");
await collection.InsertOneAsync(document);

한번에 복수의 document 추가

  • 한번의 요청으로 복수의 document를 추가한다.
var newItemList = new List<DBUserItem>();

foreach (var itemID in ItemIDList)
{
    var newData = new DBUserItem()
    {
        _id = UniqueSeqNumberGenerator(),
        UserID = userID,
        ItemID = itemID,
        AcquireDateTime = DateTime.Now,
    };

    newItemList.Add(newData);
}

var collection = GetDBCollection<DBUserItem>("Item");
await collection.InsertManyAsync(newItemList);

정렬

var collection = GetDBCollection<DBBasic>("Basic");

// 내림차순
//var documents = await collection.Find(x=> x.Level >= 1).SortByDescending(d => d.Level).FirstOrDefaultAsync();
// or
//var documents = await collection.Find(x=> x.Level >= 1).SortByDescending(d => d.Level).FirstOrDefaultAsync();
// or
//var documents = await collection.Find(x=> x.Level >= 1).SortByDescending(d => d.Level).ToListAsync();
// or 조건 없이
var documents = await collection.Find(x => true).SortByDescending(d => d.Level).ToListAsync();
var collection = GetDBCollection<BsonDocument>("Basic");

// 올림 차순
//var documents = await collection.Find(new BsonDocument()).Sort(new BsonDocument("$Level", 1)).ToListAsync();

// 내림 차순
//var documents = await collection.Find(new BsonDocument()).Sort(new BsonDocument("Level", -1)).ToListAsync();
// or
var documents = await collection.Find(new BsonDocument()).Sort("{Level: -1}").ToListAsync();
// 복수의 조건으로 정렬
var sort = Builders<BsonDocument>.Sort.Ascending("borough").Ascending("address.zipcode");
var result = await collection.Find(filter).Sort(sort).ToListAsync();

FindOneAndReplaceAsync

  • 한번에 검색&교체
var collection = GetDBCollection<DBBasic>("Basic");

var newData = new DBBasic()
{
  _id = "jacking3",
  Money = 3333,
  Costume = new List<int>(Enumerable.Repeat(0, 12))
};

// 변경 되기 이전 값을 반환한다. 실패하면 null
var documents = await collection.FindOneAndReplaceAsync(x => x._id == "jacking5", newData);
var collection = GetDBCollection<BsonDocument>("Basic");

var filter = new BsonDocument("_id", "jacking3");

// _id와 Level 필드만 도큐먼트에 남게된다.
var replacement = BsonDocument.Parse("{Level: 12}");
//var projection = BsonDocument.Parse("{x: 1}");
//var sort = BsonDocument.Parse("{a: -1}");
var options = new FindOneAndReplaceOptions<BsonDocument, BsonDocument>()
{
         IsUpsert = false, // 이것을 true로 하면 도큐먼트가 없으면 추가한다.
          //Projection = projection,
          //ReturnDocument = returnDocument,
          //Sort = sort,
          MaxTime = TimeSpan.FromSeconds(2)
};

var documents = await collection.FindOneAndReplaceAsync<BsonDocument>(filter, replacement, options, CancellationToken.None);

FindOneAndUpdateAsync

  • 한번에 검색&수정
var collection = GetDBCollection<BsonDocument>("Basic");

var filter = new BsonDocument("_id", "jacking3");
var update = BsonDocument.Parse("{$set: {Level: 3}}");
//var projection = BsonDocument.Parse("{x: 1}");
//var sort = BsonDocument.Parse("{a: -1}");
var options = new FindOneAndUpdateOptions<BsonDocument, BsonDocument>()
{
          //IsUpsert = isUpsert,
          //Projection = projection,
          //ReturnDocument = returnDocument,
          //Sort = sort,
          MaxTime = TimeSpan.FromSeconds(2)
};

var document = await collection.FindOneAndUpdateAsync<BsonDocument>(filter, update, options, CancellationToken.None);
  • BsonDocume 사용
var findUserName = textBox5.Text;
var newNickNameList = new List<string>() { textBox1.Text, textBox6.Text };

var collection = MongoDBLib.Common.GetDBCollection<BsonDocument>("GameUser2");

var filter = new BsonDocument("_id", findUserName);
var update = Builders<BsonDocument>.Update.Set("NickNameList", new BsonArray(newNickNameList));
var options = new FindOneAndUpdateOptions<BsonDocument, BsonDocument>
{
    ReturnDocument = ReturnDocument.After
};

var document = await collection.FindOneAndUpdateAsync<BsonDocument>(filter, update, options);

if (document == null)
{
    DevLog.Write(string.Format("GameUser2:{0} 닉네임 변경 실패", findUserName));
}
else
{
    var nickList = document["NickNameList"].AsBsonArray.Select(p => p.AsString).ToList();

    DevLog.Write(string.Format("GameUser2:{0} 닉네임 변경 {1}, {2}", findUserName, nickList[0], nickList[1]));
}
  • 클래스 맵핑 사용
var findUserName = textBox5.Text;
var newNickNameList = new List<string>() { textBox1.Text, textBox6.Text };

var collection = MongoDBLib.Common.GetDBCollection<GameUser2>("GameUser2");

var result = await collection.FindOneAndUpdateAsync<GameUser2>(
                u => u._id == findUserName, 
                Builders<GameUser2>.Update.Set("NickNameList", new BsonArray(newNickNameList)), 
    new FindOneAndUpdateOptions<GameUser2, GameUser2>
    {
        ReturnDocument = ReturnDocument.After
    });

if (result == null)
{
    DevLog.Write(string.Format("GameUser2:{0} 닉네임 변경 실패", findUserName)); 
}
else
{
    DevLog.Write(string.Format("GameUser2:{0} 닉네임 변경 {1}, {2}", findUserName, result.NickNameList[0], result.NickNameList[1]));
}

동적 기능 사용하기

  • C#의 다이나믹 타입 사용
dynamic person = new System.Dynamic.ExpandoObject();
person.FirstName = "Jane";
person.Age = 12;
person.PetNames = new List<dynamic> { "Sherlock", "Watson" };

var collection = GetDBCollection<dynamic>("Persion");
await collection.InsertOneAsync(person);

UTC 시간 보정해서 데이터 넣기

  • MongoDB에 time 타입 데이터는 utc 기준으로 들어간다. 그래서 mongodb에서 보이는데 시간을 한국 시간과 같게 하려면 도큐먼트를 넣을 때 시간을 +9 한다.
var newData = new DBTimeData()
{
        CurTime = DateTime.Now.AddHours(9)
};

var collection = GetDBCollection<DBTimeData>("TimeData");
await collection.InsertOneAsync(newData);

Update

기본 업데이트

// UpdateOneAsync 는 하나만, 복수는 UpdateManyAsync
var collection = GetDBCollection<DBUserSkill>("Skill");

var userID = "jacking";

var result = await collection.UpdateOneAsync(x => x._id == userID,
                                Builders<DBUserSkill>.Update.Set(x => x.Value, 14));
// result.MatchedCount 가 1 보다 작으면 업데이트 한 것이 없음

도큐먼트의 내부 도큐먼트를 변경할 때

var collection = GetDBCollection<DBUserSkill>("Skill");

var userID = "jacking";
int skillItemID = 1;
var newInfo = new SkillItemInfo() { Value = 101 };


var filter = Builders<DBUserSkill>.Filter.And(Builders<DBUserSkill>.Filter.Eq(x => x._id, userID),
                                                  Builders<DBUserSkill>.Filter.ElemMatch(x => x.SkillItems, x => x.ID == skillItemID));

var update = Builders<DBUserSkill>.Update.Set("SkillItems.$.Info", newInfo);
//or
//var update = Builders<DBUserSkill>.Update.Set(x => x.SkillItems.ElementAt(-1).Info, newInfo);

collection.UpdateOneAsync(filter, update);

Replace

var collection = GetDBCollection<DBBasic>("Basic");

var userID = "jacking";
var documents = await collection.Find(x=> x._id == userID).SingleAsync();

if( documents != null)
{
documents.Level = documents.Level + 3;
var result = await collection.ReplaceOneAsync(x => x._id == documents._id, documents);
var tom = await collection.Find(x => x.Id == ObjectId.Parse("550c4aa98e59471bddf68eef"))
        .SingleAsync();

tom.Name = "Thomas";
tom.Age = 43;
tom.Profession = "Hacker";

var result = await collection.ReplaceOneAsync(x => x.Id == tom.Id, tom);

Delete

삭제. 한번에 복수개를 지울 때는 DeleteManyAsync

var collection = GetDBCollection<DBBasic>("Basic");

var userID = "jacking4";
var result = await collection.DeleteOneAsync(x=> x._id == userID);

이 글은 2019-04-25에 작성되었습니다.