├── .gitignore ├── LICENSE ├── MongoDBCSharp.md ├── MongoDBCSharpVer2.md ├── README.md ├── XamarinWorkbooks └── mongoDB_delete.workbook ├── find.md ├── insert_update_delete.md ├── tips.md ├── windowsInstall.md └── wiredTiger.md /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studo 2015 cache/options directory 26 | .vs/ 27 | 28 | # MSTest test Results 29 | [Tt]est[Rr]esult*/ 30 | [Bb]uild[Ll]og.* 31 | 32 | # NUNIT 33 | *.VisualState.xml 34 | TestResult.xml 35 | 36 | # Build Results of an ATL Project 37 | [Dd]ebugPS/ 38 | [Rr]eleasePS/ 39 | dlldata.c 40 | 41 | *_i.c 42 | *_p.c 43 | *_i.h 44 | *.ilk 45 | *.meta 46 | *.obj 47 | *.pch 48 | *.pdb 49 | *.pgc 50 | *.pgd 51 | *.rsp 52 | *.sbr 53 | *.tlb 54 | *.tli 55 | *.tlh 56 | *.tmp 57 | *.tmp_proj 58 | *.log 59 | *.vspscc 60 | *.vssscc 61 | .builds 62 | *.pidb 63 | *.svclog 64 | *.scc 65 | 66 | # Chutzpah Test files 67 | _Chutzpah* 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | *.cachefile 76 | 77 | # Visual Studio profiler 78 | *.psess 79 | *.vsp 80 | *.vspx 81 | 82 | # TFS 2012 Local Workspace 83 | $tf/ 84 | 85 | # Guidance Automation Toolkit 86 | *.gpState 87 | 88 | # ReSharper is a .NET coding add-in 89 | _ReSharper*/ 90 | *.[Rr]e[Ss]harper 91 | *.DotSettings.user 92 | 93 | # JustCode is a .NET coding addin-in 94 | .JustCode 95 | 96 | # TeamCity is a build add-in 97 | _TeamCity* 98 | 99 | # DotCover is a Code Coverage Tool 100 | *.dotCover 101 | 102 | # NCrunch 103 | _NCrunch_* 104 | .*crunch*.local.xml 105 | 106 | # MightyMoose 107 | *.mm.* 108 | AutoTest.Net/ 109 | 110 | # Web workbench (sass) 111 | .sass-cache/ 112 | 113 | # Installshield output folder 114 | [Ee]xpress/ 115 | 116 | # DocProject is a documentation generator add-in 117 | DocProject/buildhelp/ 118 | DocProject/Help/*.HxT 119 | DocProject/Help/*.HxC 120 | DocProject/Help/*.hhc 121 | DocProject/Help/*.hhk 122 | DocProject/Help/*.hhp 123 | DocProject/Help/Html2 124 | DocProject/Help/html 125 | 126 | # Click-Once directory 127 | publish/ 128 | 129 | # Publish Web Output 130 | *.[Pp]ublish.xml 131 | *.azurePubxml 132 | # TODO: Comment the next line if you want to checkin your web deploy settings 133 | # but database connection strings (with potential passwords) will be unencrypted 134 | *.pubxml 135 | *.publishproj 136 | 137 | # NuGet Packages 138 | *.nupkg 139 | # The packages folder can be ignored because of Package Restore 140 | **/packages/* 141 | # except build/, which is used as an MSBuild target. 142 | !**/packages/build/ 143 | # Uncomment if necessary however generally it will be regenerated when needed 144 | #!**/packages/repositories.config 145 | 146 | # Windows Azure Build Output 147 | csx/ 148 | *.build.csdef 149 | 150 | # Windows Store app package directory 151 | AppPackages/ 152 | 153 | # Others 154 | *.[Cc]ache 155 | ClientBin/ 156 | [Ss]tyle[Cc]op.* 157 | ~$* 158 | *~ 159 | *.dbmdl 160 | *.dbproj.schemaview 161 | *.pfx 162 | *.publishsettings 163 | node_modules/ 164 | bower_components/ 165 | 166 | # RIA/Silverlight projects 167 | Generated_Code/ 168 | 169 | # Backup & report files from converting an old project file 170 | # to a newer Visual Studio version. Backup files are not needed, 171 | # because we have git ;-) 172 | _UpgradeReport_Files/ 173 | Backup*/ 174 | UpgradeLog*.XML 175 | UpgradeLog*.htm 176 | 177 | # SQL Server files 178 | *.mdf 179 | *.ldf 180 | 181 | # Business Intelligence projects 182 | *.rdl.data 183 | *.bim.layout 184 | *.bim_*.settings 185 | 186 | # Microsoft Fakes 187 | FakesAssemblies/ 188 | 189 | # Node.js Tools for Visual Studio 190 | .ntvs_analysis.dat 191 | 192 | # Visual Studio 6 build log 193 | *.plg 194 | 195 | # Visual Studio 6 workspace options file 196 | *.opt 197 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Choi HeungBae 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /MongoDBCSharp.md: -------------------------------------------------------------------------------- 1 | 2 | [TOC] 3 | 4 | 5 | 6 | ###MongoDB 공식 C# Driver 7 | - CSharp Language Center 8 | http://docs.mongodb.org/ecosystem/drivers/csharp/ 9 | - CSharp Driver Tutorial 10 | http://docs.mongodb.org/ecosystem/tutorial/use-csharp-driver/#csharp-driver-tutorial 11 | - 1.8.1 버전 API 문서 12 | http://api.mongodb.org/csharp/1.8.1/ 13 | 14 | 15 | 16 | ###접속 시 인증 17 | ``` 18 | // on the connection string 19 | var connectionString = "mongodb://user:pwd@localhost/?safe=true"; 20 | var server = MongoServer.Create(connectionString); 21 | 22 | // in code 23 | var settings = new MongoServerSettings() { 24 | DefaultCredentials = new MongoCredentials("user", "pwd"), 25 | SafeMode = SafeMode.True 26 | }; 27 | 28 | var server = MongoServer.Create(settings); 29 | ``` 30 | 31 | ###서로 인증 정보가 다른 database를 사용할 때 32 | ``` 33 | var credentialsStore = new MongoCredentialsStore(); 34 | credentialsStore.AddCredentials( 35 | "hr", new MongoCredentials("user1", "pwd1")); 36 | credentialsStore.AddCredentials( 37 | "inventory", new MongoCredentials("user2", "pwd2")); 38 | 39 | var settings = new MongoServerSettings { 40 | CredentialsStore = credentialsStore, 41 | SafeMode = SafeMode.True 42 | }; 43 | 44 | var server = MongoServer.Create(settings); 45 | var credentials = new MongoCredentials("user", "pwd"); 46 | var database = server.GetDatabase("hr", credentials); 47 | ``` 48 | 49 | 50 | ###Admin으로 인증하기 51 | ``` 52 | var cs = "mongodb://user(admin):pwd@localhost/?safe=true"; 53 | var server = MongoServer.Create(cs); 54 | 55 | var adminCredentials = new MongoCredentials("user", "pwd", true); 56 | var settings = new MongoServerSettings { 57 | DefaultCredentials = adminCredentials, 58 | SafeMode = SafeMode.True 59 | }; 60 | 61 | var server = MongoServer.Create(settings); 62 | ``` 63 | 64 | 65 | ###옵션 설정하기 66 | - connection pool 크기 설정 67 | ConnectString="mongodb://172.20.60.221:27018/?maxPoolSize=256" 68 | - 옵션 설정 예제 코드 69 | https://github.com/mongodb/mongo-csharp-driver/blob/master/MongoDB.DriverUnitTests/MongoClientSettingsTests.cs 70 | 71 | 72 | 73 | ###시간 사용 74 | ####MongoDB에서 사용할 수 있는 현재 시간 변환. 75 | MongoDB는 유니버셜 시간대를 사용하고 있으므로 시간을 그냥 사용하면 현재 시간 -9 시간으로 변환되어 버린다. 76 | ``` 77 | public static DateTime GetLocalTime() 78 | { 79 | string strCurDateTime = DateTime.Now.ToString("yyyyMMddHHmmss"); 80 | IFormatProvider culture = new System.Globalization.CultureInfo("", true); 81 | 82 | DateTime LocalDateTime = DateTime.ParseExact(strCurDateTime, "yyyyMMddHHmmss", culture, System.Globalization.DateTimeStyles.AssumeUniversal); 83 | 84 | return LocalDateTime; 85 | } 86 | ``` 87 | 88 | ####입력 89 | - 201308011121 라는 문자열로 DateTime 객체를 만든다. 90 | - 중요: MongoDB는 UTC date 타임대를 사용하므로 91 | 92 | ``` 93 | System.Globalization.DateTimeStyles.AssumeUniversal 로 조정한다 94 | IFormatProvider culture = new System.Globalization.CultureInfo("", true); 95 | DateTime date = DateTime.ParseExact(date_time, "yyyyMMddHHmm", culture, System.Globalization.DateTimeStyles.AssumeUniversal); 96 | 97 | 98 | var login = BasicLogDB.GetCollection("Login"); 99 | 100 | BsonDocument data = new BsonDocument() 101 | { 102 | {"ID", id}, 103 | {"UniqNum", UniqueNumber}, 104 | {"date", date} 105 | }; 106 | 107 | login.Insert(data); 108 | ``` 109 | 110 | 111 | ###예제 Insert 112 | ####기본 113 | ``` 114 | using MongoDB.Bson; 115 | using MongoDB.Driver; 116 | using MongoDB.Driver.Builders; 117 | 118 | MongoClient cli = new MongoClient(textBoxAddress.Text); 119 | MongoDatabase testdb = cli.GetServer().GetDatabase("test"); 120 | 121 | MongoCollection Customers = testdb.GetCollection("Account"); 122 | 123 | try 124 | { 125 | for (int i = 0; i < Count; ++i) 126 | { 127 | BsonDocument data = new BsonDocument() 128 | { 129 | {"ID", string.Format("{0}{1}",textBoxPreFix.Text, (StartIndex+i).ToString())}, 130 | {"PW", "1111"} 131 | }; 132 | 133 | var result = Customers.Insert(data); 134 | 135 | if(result.Ok == false) 136 | return false; 137 | } 138 | } 139 | catch (Exception err) 140 | { 141 | MessageBox.Show(err.ToString()); 142 | } 143 | ``` 144 | 145 | ####제너릭 데이터를 사용한 추가 146 | ``` 147 | ... 148 | 149 | userInfo = new UserInfo 150 | { 151 | UserIndex = 1, 152 | ID = id, 153 | PW = pw, 154 | }; 155 | 156 | var result = Coll.Insert(userInfo); 157 | 158 | if (result.Ok == false) 159 | { 160 | return null; 161 | } 162 | ``` 163 | 164 | ####다수의 값을 한번에 추가할 때 InsertBatck 165 | - 복사할 곳(dest)에 복사대상(source)와 같은 index를 가진 것이 있으면 안 된다. 166 | 167 | ``` 168 | MongoCollection books; 169 | BsonDocument[] batch = { 170 | new BsonDocument { 171 | { "author", "Kurt Vonnegut" }, 172 | { "title", "Cat's Cradle" } 173 | }, 174 | new BsonDocument { 175 | { "author", "Kurt Vonnegut" }, 176 | { "title", "Slaughterhouse-Five" } 177 | } 178 | }; 179 | books.InsertBatch(batch); 180 | var squadList = new List(); 181 | squadList.Add(new CharData 182 | { 183 | UserIndex = userIndex, 184 | Slot = 0, 185 | }); 186 | squadList.Add(new CharData 187 | { 188 | UserIndex = userIndex, 189 | Slot = 1, 190 | }); 191 | 192 | var result = Coll.InsertBatch(squadList); 193 | 194 | if (result.Count() != 1) 195 | { 196 | return false; 197 | } 198 | ``` 199 | 200 | 201 | ###문자열을 ObjectId로 변환하기 202 | ``` 203 | var query_id = Query.EQ("_id", ObjectId.Parse("50ed4e7d5baffd13a44d0153")); 204 | // 몽고디비 툴에서 검색할 때 205 | db.Users.find( {_id:ObjectId("546173b07c935c15942aa233")}) 206 | ``` 207 | 208 | 209 | 210 | ###예제 Select 211 | ####하나만 반환 212 | - 검색된 것이 없을 때는 null 반환. 그러나 하나 이상 있을 때는 예외 발생 213 | 214 | ``` 215 | public static bool Auth(string id, string pw) 216 | { 217 | try 218 | { 219 | MongoClient cli = new MongoClient("mongodb://172.20.60.221"); 220 | MongoDatabase database = cli.GetServer().GetDatabase("test"); 221 | var Accounts = database.GetCollection("Account"); 222 | 223 | IMongoQuery query = Query.EQ("ID", id); 224 | var result = Accounts.Find(query).SingleOrDefault(); 225 | 226 | if (result == null) 227 | { 228 | return false; 229 | } 230 | 231 | if (result["PW"] != pw) 232 | { 233 | return false; 234 | } 235 | } 236 | catch(Exception ex) 237 | { 238 | return false; 239 | } 240 | 241 | return true; 242 | } 243 | ``` 244 | 245 | ####여러개 반환 246 | ``` 247 | IMongoQuery query = Query.EQ("version", version); 248 | var results = ItemInfo.Find(query); 249 | 250 | 251 | List itemlist = new List(); 252 | 253 | foreach (var iteminfo in results) 254 | { 255 | var item = new ItemInfo 256 | { 257 | version = version, 258 | ID = iteminfo["ID"].AsInt32, 259 | name = iteminfo["name"].AsString, 260 | Lv = iteminfo["Lv"].AsInt32 261 | }; 262 | 263 | itemlist.Add(item); 264 | } 265 | // 266 | public class ItemInfo 267 | { 268 | public int version; 269 | public int ID; 270 | public string name; 271 | public int Lv; 272 | } 273 | ``` 274 | 275 | ####Where절 사용 276 | ``` 277 | Query.Where(d => d.EmployeeNumber == 1234) 278 | Query.Where(d => d.Name == "John Doe") 279 | Query.Where(d => d.EmployeeStatus != Status.Active) 280 | Query.Where(d => d.Salary > 100000) 281 | ``` 282 | 283 | ####복합 쿼리 284 | ``` 285 | var query = Query.GTE("x", 1).LTE(3); 286 | // becomes 287 | var query = Query.And(Query.GTE("x", 1), Query.LTE("x", 3)); 288 | 289 | var query = Query.Not("x").GT(1); 290 | // becomes 291 | var query = Query.Not(Query.GT("x", 1)); 292 | 293 | var query = Query.Exists("x", true); 294 | // becomes 295 | var query = Query.Exists("x"); 296 | 297 | var query = Query.Exists("x", false); 298 | // becomes 299 | var query = Query.NotExists("x"); 300 | ``` 301 | 302 | ####해당 collection 모든 데이터 가져오기 303 | ``` 304 | List lstAccount = new List(); 305 | 306 | MongoClient cli = new MongoClient("mongodb://172.20.60.221"); 307 | MongoDatabase database = cli.GetServer().GetDatabase("WebTest"); 308 | var Accounts = database.GetCollection("Account"); 309 | 310 | // query문 없이 FindAll 사용, 해당 collection에 모든 데이터를 가져올 수 있다. 311 | var result = Accounts.FindAll(); 312 | 313 | foreach (var AccountInfo in result) 314 | { 315 | var Account = new AccountData 316 | { 317 | AccountID = AccountInfo["ID"].AsString, 318 | PassWord = AccountInfo["PW"].AsDouble 319 | }; 320 | } 321 | return lstAccount; 322 | ``` 323 | 324 | ###First, Last 325 | - First는 제일 첫 번째, Last는 제일 마지막 도큐먼트 반환한다. 그러나 컬렉션에 도큐먼트가 하나도 없는 경우 예외가 발생한다. 326 | - 그래서 안전하게 사용하고 싶다면 FirstOrDefault, LastOrDefult를 사용하는 것이 좋다. 327 | - Default로 만들기 위해 델리게이트 지정을 안하면 null이 반환된다 328 | 329 | 330 | ###예제 Update, Delete 331 | ``` 332 | // http://www.csharpstudy.com/Tips/Tips-mongodb.aspx 333 | // Mongo DB를 위한 Connection String 334 | string connString = "mongodb://localhost"; 335 | 336 | // MongoClient 클라이언트 객체 생성 337 | MongoClient cli = new MongoClient(connString); 338 | 339 | // testdb 라는 데이타베이스 가져오기 340 | // 만약 해당 DB 없으면 Collection 생성시 새로 생성함 341 | MongoDatabase testdb = cli.GetServer().GetDatabase("testdb"); 342 | 343 | // testdb 안에 Customers 라는 컬렉션(일종의 테이블) 344 | // 가져오기. 만약 없으면 새로 생성. 345 | var customers = testdb.GetCollection("Customers"); 346 | 347 | // INSERT - 컬렉션 객체의 Insert() 메서드 호출 348 | // Insert시 _id 라는 자동으로 ObjectID 생성 349 | // 이 _id는 해당 다큐먼트는 나타는 키. 350 | Customer cust1 = new Customer { Name = "Kim", Age = 30 }; 351 | customers.Insert(cust1); 352 | ObjectId id = cust1.Id; 353 | 354 | // SELECT - id로 검색 355 | IMongoQuery query = Query.EQ("_id", id); 356 | var result = customers.Find(query).SingleOrDefault(); 357 | if (result != null) 358 | { 359 | Console.WriteLine(result.ToString()); 360 | } 361 | 362 | // UPDATE 363 | // Save() = 전체 다큐먼트 갱신. 364 | // Update() = 부분 수정 365 | cust1.Age = 31; 366 | customers.Save(cust1); 367 | 368 | // DELETE 369 | var qry = Query.EQ("_id", id); 370 | customers.Remove(qry); 371 | ``` 372 | 373 | 데이터가 없으면 추가하고, 있다면 업데이트 하기 374 | ``` 375 | static void SaveServerHeartBeatInfo_Callback(Object state) 376 | { 377 | try 378 | { 379 | ... 380 | var collection = database.GetCollection("컬렉션"); 381 | var findData = collection.FindOne(MongoDB.Driver.Builders.Query.EQ("name", id)); 382 | 383 | if (findData == null) 384 | { 385 | var saveData = new SAVE_DATA 386 | { 387 | Name = id, 388 | value = 1000 389 | }; 390 | 391 | collection.Save(saveData); 392 | } 393 | else 394 | { 395 | findData.value = 1001; 396 | collection.Save(findData); 397 | } 398 | } 399 | catch (Exception ex) 400 | { 401 | } 402 | } 403 | ``` 404 | 405 | 406 | ###예제 FindAndModify 407 | ``` 408 | var modifyArgs = new MongoDB.Driver.FindAndModifyArgs() 409 | { 410 | Query = Query.EQ("_id", objID), 411 | Update = Update.Set("MaxBuild", maxBuild), 412 | Fields = Fields.Include("MaxBuild"), // 이걸 지정하지 않으면 모든 필드의 값을 가져온다. 413 | SortBy = SortBy.Null, 414 | VersionReturned = MongoDB.Driver.FindAndModifyDocumentVersion.Modified, // 변경된 값을 가져온다. 415 | Upsert = false, // 없으면 추가하지 않는다 416 | }; 417 | 418 | var newResult = collection.FindAndModify(modifyArgs); 419 | 420 | // 검색 실패이면 null 421 | if (newResult.ModifiedDocument == null) 422 | { 423 | return false; 424 | } 425 | 426 | return true; 427 | ``` 428 | 429 | 430 | 431 | ###증분으로 업데이트 하기 432 | ``` 433 | var modifyArgs = new MongoDB.Driver.FindAndModifyArgs() 434 | { 435 | Query = Query.EQ("_id", objID), 436 | Update = Update.Inc("Money", change), 437 | Fields = Fields.Include("Money"), 438 | SortBy = SortBy.Null, 439 | VersionReturned = MongoDB.Driver.FindAndModifyDocumentVersion.Modified, 440 | Upsert = false, 441 | }; 442 | ``` 443 | 444 | 445 | 446 | ###복수 데이터 일괄 Update 447 | ``` 448 | var ub = new UpdateBuilder(); 449 | ub.Set("Money", inputData.Money); 450 | ub.Set("Exp", inputData.Exp); 451 | ub.Set("Level", inputData.Level); 452 | collection.Update(Query.EQ("UserID", inputData.UserID), ub); 453 | ``` 454 | 455 | 456 | 457 | ###특정 필드 제외, 특정 필드만 쿼리하기 458 | 특정 필드 제외 459 | ``` 460 | MongoClient cli = new MongoClient(DB_ConnectString); 461 | MongoDatabase db = cli.GetServer().GetDatabase(BasicLogDatabaseName); 462 | var UniqueNumberCol = db.GetCollection("UniqueNumber"); 463 | 464 | // _id 필드만 제외하고 모든 필드 데이터를 가져온다 465 | var newResult = UniqueNumberCol.FindAll().SetFields(Fields.Exclude("_id")); 466 | ``` 467 | 468 | 특정 필드만 가져오기 469 | ``` 470 | MongoClient cli = new MongoClient(DB_ConnectString); 471 | MongoDatabase db = cli.GetServer().GetDatabase(BasicLogDatabaseName); 472 | var UniqueNumberCol = db.GetCollection("UniqueNumber"); 473 | 474 | // money, level 필드 데이터만 가져온다 475 | var newResult = UniqueNumberCol.FindAll().SetFields(Fields.include("money", "level")); 476 | ``` 477 | 478 | 479 | 480 | ###날짜 쿼리 481 | 특정날짜의 데이터 개수 알아내기 482 | ``` 483 | // 어제 날짜 484 | dateTime = DateTime.Now.AddDays(-1); 485 | // 0시로 만들기 위해서 486 | DateTime dateTime2 = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day); 487 | var count = DBWork.DBDataMining.DailyNewUserStatistics(db, dateTime2); 488 | 489 | static public long DailyNewUserStatistics(MongoDBLib dbLib, DateTime dateTime) 490 | { 491 | var collection = dbLib.BasicLogDB.GetCollection("NewUser"); 492 | 493 | // 494 | var query = Query.And(Query.GTE("date", dateTime.ToUniversalTime()), Query.LTE("date", dateTime.AddDays(1).ToUniversalTime())); 495 | var count = collection.Find(query).Count(); 496 | return count; 497 | } 498 | ``` 499 | 500 | 501 | 502 | ###중복 제외 503 | ``` 504 | //{ 505 | // "_id" : ObjectId("5209d0507dbe2af068a42aec"), 506 | // "ID" : "jacking75", 507 | // "Uniq" : 5, 508 | // "date" : ISODate("2013-08-12T06:21:04Z") 509 | //} 510 | 511 | DateTime datetime = MongoDBLib.StringToDateTime(yyyyMMddHHmm); 512 | 513 | // 로그인한 총 수를 얻는다 514 | var collection = dbLib.BasicLogDB.GetCollection("LoginUser"); 515 | var query = Query.And(Query.GTE("date", datetime), Query.LTE("date", datetime.AddDays(1))); 516 | 517 | // ID 필드 값 중 중복된 것을 제외하고 개수를 구한다 518 | var UniqueLoginUserCount = collection.Distinct("ID", query).Count(); 519 | ``` 520 | 521 | 522 | 523 | ###배열 추가 524 | 데이터가 배열인 경우 525 | ``` 526 | var mongoClient = MongoDBLib.GetGameClient(MongoDBLib.GAME_DATABASE, userIndex); 527 | 528 | var database = mongoClient.GetServer().GetDatabase(MongoDBLib.GAME_DATABASE); 529 | var collection = database.GetCollection(MongoDBLib.CLEARED_STAGE_LIST_COLLECTION); 530 | 531 | var result = collection.Update(Query.EQ("UserIndex", userIndex), Update.PushWrapped("StageIDList", stageID)); 532 | isResult = result.UpdatedExisting; 533 | ``` 534 | 535 | List 자료구조를 추가하기 536 | ``` 537 | int[] defaultValue = {0, 0, 0, 0, 0, 0, 0, 0}; 538 | List aaa = new List(defaultValue); 539 | 540 | 541 | var mongoClient = MongoDBLib.GetGameClient(); 542 | MongoDatabase db = mongoClient.GetServer().GetDatabase("GAME_DATABASE"); 543 | var Coll = db.GetCollection("collection"); 544 | 545 | BsonDocument data = new BsonDocument() 546 | { 547 | {"UserIndex", userIndex}, 548 | {"Squard1", new BsonArray(aaa)}, 549 | {"Squard2", new BsonArray(aaa)}, 550 | {"Squard3", new BsonArray(aaa)}, 551 | }; 552 | int[] 기본값 = { 0, 0, 0, 0, 0, 0, 0, 0 }; 553 | 554 | var Coll = db.GetCollection(MongoDBLib.CHARACTER_SQUARD_COLLECTION); 555 | 556 | var squadList = new List(); 557 | squadList.Add(new CharInfo 558 | { 559 | UserIndex = userIndex, 560 | ItemIDs = 기본값.ToList(), 561 | }); 562 | squadList.Add(new CharInfo 563 | { 564 | UserIndex = userIndex, 565 | ItemIDs = 기본값.ToList(), 566 | }); 567 | squadList.Add(new CharInfo 568 | { 569 | UserIndex = userIndex, 570 | ItemIDs = 기본값.ToList(), 571 | }); 572 | 573 | var result = Coll.InsertBatch(squadList); 574 | 575 | if (result.Count() != 1) 576 | { 577 | return false; 578 | } 579 | ``` 580 | 581 | 582 | 583 | ###배열 전체 업데이트 584 | ``` 585 | List usePosList; 586 | Update = Update.Set("UseBPosList", new BsonArray(usePosList)) 587 | ``` 588 | 589 | 590 | 591 | ###배열의 특정 요소만 업데이트 592 | ``` 593 | var aValue = new AA(); 594 | 595 | // AList의 1번 인덱스(두번째 위치)의 값을 바꾼다. 596 | var query = Query.And(Query.EQ("UserID", userID), Query.EQ("Type", type)); 597 | var update = Update.Set("AList." + 1, new BsonDocumentWrapper(aValue)); 598 | 599 | collection.Update(query, update); 600 | ``` 601 | 602 | 603 | 604 | ###BSonDocument에서 배열 데이터 읽기 605 | ``` 606 | // 도큐먼트 607 | //{ 608 | // "Cash" : 100, 609 | // "UseList" : [ false, false, false ], 610 | //} 611 | 612 | var dataList = collection.Find(query); 613 | 614 | foreach (var data in dataList) 615 | { 616 | returnValue.Cash = data["Cash"].AsInt32; 617 | returnValue.UseList = data["UseBPosList"].AsBsonArray.Select(p => p.AsBoolean).ToList(); 618 | } 619 | ``` 620 | 621 | 622 | 623 | ###skip & limit 624 | ``` 625 | Console.WriteLine(collection.Find(query).SetSkip(0).SetLimit(1).Size()); 626 | ``` 627 | 628 | 629 | 630 | ###제일 마지막 레코드 가져오기 631 | ``` 632 | ... 633 | MongoCollection table = db.GetCollection("Collection"); 634 | var tableCount = (int)table.Count(); 635 | 636 | var skipCount = tableCount - 1; 637 | var result = table.FindAll().SetSkip(skipCount); 638 | 639 | // result.Size() == 1 이면 제일 마지막 것만 가져온 것 이다. 640 | ``` 641 | 642 | 643 | 644 | ###SP 실행 645 | SP(저장프로시저) 코드를 직접 사용 646 | ``` 647 | var mongoClient = MongoDBLib.GetAccountClient(); 648 | var database = mongoClient.GetServer().GetDatabase(MongoDBLib.ACCOUNT_DATABASE); 649 | 650 | BsonValue bv1 = database.Eval("function(x, y) { return x + y; }", x, y); 651 | return (int)bv1.AsDouble; 652 | ``` 653 | 654 | 몽고DB에 저장된 SP를 가져와서 실행 655 | ``` 656 | // 몽고DB 데이터베이스의 Functions에 TestSumSP라는 이름의 SP("function(x, y) { return x + y; }")를 만들어 놓음 657 | var mongoClient = MongoDBLib.GetAccountClient(); 658 | var database = mongoClient.GetServer().GetDatabase(MongoDBLib.ACCOUNT_DATABASE); 659 | 660 | BsonValue bv = database.Eval("TestSumSP", x, y); 661 | BsonValue bv1 = database.Eval(bv.AsBsonJavaScript.Code, x, y); 662 | return (int)bv1.AsDouble; 663 | ``` 664 | 665 | 666 | 667 | ###SP 호출로 데이터 얻기 668 | ``` 669 | static string SP_GET_USER = @"function(userID, companyName) 670 | { 671 | var cursor = db.User.find( {$or:[{Name: companyName}, {ID: userID}]} ) 672 | var hasData = cursor.hasNext() ? cursor.next() : null; 673 | return hasData; 674 | }"; 675 | public static bool GetUser(string userID, string name) 676 | { 677 | bool result = false; 678 | 679 | try 680 | { 681 | var mongoClient = MongoDBLib.GetAccountClient(); 682 | MongoDatabase db = mongoClient.GetServer().GetDatabase("AccountDB"); 683 | BsonValue bv = db.Eval(SP_GET_USER, userID, name); 684 | ... 685 | 686 | result = true; 687 | } 688 | catch (Exception ex) 689 | { 690 | return false; 691 | } 692 | 693 | return result; 694 | } 695 | ``` 696 | 697 | 698 | 699 | ###중복 금지 700 | - 인덱스 사용. 컬렉션에서 중복되면 안되는 필드에 인덱스(유니크)를 걸어서 중복으로 추가되지 않도록 한다. 701 | C#에서 위와 같은 이유로(데이터 중복에 의해) 추가가 실패하면 예외가 발생한다. 702 | - SP 사용 703 | 704 | ``` 705 | static string SP_ADD_USER = @"function(userID, companyName) 706 | { 707 | var cursor = db.User.find( {$or:[{Name: companyName}, {ID: userID}]} ) 708 | var hasData = cursor.hasNext() ? cursor.next() : null; 709 | if(hasData) 710 | { 711 | return false; 712 | } 713 | 714 | db.User.insert({ ID:userID, Name:companyName }) 715 | return true; 716 | }"; 717 | public static bool AddUser(UserInfo userInfo) 718 | { 719 | bool result = false; 720 | 721 | try 722 | { 723 | var mongoClient = MongoDBLib.GetAccountClient(); 724 | MongoDatabase db = mongoClient.GetServer().GetDatabase("AccountDB"); 725 | BsonValue bv = db.Eval(SP_ADD_USER, userInfo.ID, userInfo.Name); 726 | result = bv.AsBoolean; 727 | } 728 | catch (Exception ex) 729 | { 730 | return false; 731 | } 732 | 733 | return result; 734 | } 735 | ``` 736 | 737 | ###정렬 738 | - 데이터 개수가 많고 정렬한 데이터를 각각 업데이트 해야 한다면 MongoDB가 아닌 프로그램의 메모리 상에서 직접 정렬하는 것이 좋다. 739 | - MongoDB가 느린 이유는 정렬자체 보다는 정렬 후 업데이트를 위해서 문서 하나하나를 업데이트 해야 하는 비용이 비싸기 때문이다. 740 | - 업데이트라서 InsertBatch를 사용할 수 없어서 업데이트에 많은 비용이 소비된다. 741 | - 그래서 프로그램에서 DB의 데이터를 가져온 후 직접 정렬한 후 기존 컬렉션의 데이터를 지우고 InserBatch로 새로 데이터를 넣는 것이 훨씬 더 좋다 742 | - 정렬에 제한이 있다. 정렬할 데이터가 메모리 상에 32MB를 넘으면 안 된다. 그래서 정렬에 사용되는 필드는 모두 인덱스에 걸어야 한다. 743 | 744 | ``` 745 | // 정렬 조건 TotalScore가 큰 수, Level이 큰 수, UID가 작은 수 746 | // 복합 인덱스를 건다 db.WeekTotalNetProfit.ensureIndex({ TotalScore: -1, Level: -1, UID: 1 }) 747 | public class DBUserWeekTotalNetProfit 748 | { 749 | public string _id; 750 | public int Level; 751 | public Int64 UID; 752 | public Int64 TotalScore; 753 | public int TotalTurn; 754 | public int PrevOrder; // 전날 랭킹 순위 755 | public int Order; // 순위 756 | } 757 | 758 | try 759 | { 760 | var sortBy = SortBy.Descending(m => m.TotalScore).Descending(m => m.Level).Ascending(m => m.UID); 761 | var userDataSources = MongoDBLib.GetUserWeekTotalNetProfitCollection(); 762 | 763 | int ord = 0; 764 | foreach (var userDataSource in userDataSources.FindAll().SetSortOrder(sortBy)) 765 | { 766 | ord++; 767 | userDataSource.PrevOrder = userDataSource.Order; 768 | userDataSource.Order = ord; 769 | userDataSources.Save(userDataSource); 770 | } 771 | } 772 | catch (Exception ex) 773 | { 774 | } 775 | ``` 776 | 777 | ``` 778 | // BSonDocument 사용 시 779 | var dbCollection = Collection(); 780 | var dataList = dbCollection.FindAll().SetSortOrder(SortBy.Descending("TotalScore")); 781 | ``` 782 | 783 | 784 | ###컬렉션 복사 785 | ``` 786 | var sourceCollection = MongoDBLib.GetUserWeekTotalNetProfitCollection(); 787 | var resultCollection = MongoDBLib.GetUserWeekTotalNetProfitResultCollection(); 788 | 789 | resultCollection.RemoveAll(); 790 | resultCollection.InsertBatch(sourceCollection.FindAll()); 791 | ``` 792 | 793 | 794 | ###LINQ 795 | - (일어)mongoDB에서도 LINQ를 사용하자 796 | http://cerberus1974.hateblo.jp/entry/2012/12/13/000245 797 | 798 | ####기본 799 | ``` 800 | MongoDB.Driver 801 | MongoDB.Driver.Builders 802 | MongoDB.Driver.Linq 803 | MongoDB.Bson 804 | MongoDB.Bson.Serialization.Attributes 805 | [BsonIgnoreExtraElements] 806 | public class AddressEntry 807 | { 808 | [BsonId] 809 | public BsonObjectId _id { get; set;} 810 | public string Name { get; set; } 811 | public DateTime Birthday { get; set; } 812 | public List EmailAddrs { get; set; } 813 | 814 | [BsonIgnore] 815 | public string Detail { get; set; } // 맵핑하지 않는다 816 | } 817 | 818 | [BsonIgnoreExtraElements] 819 | public class Email 820 | { 821 | public string DisplayName { get; set; } 822 | public string MailAddress { get; set; } 823 | } 824 | 825 | 826 | // MongoDB에 접속 827 | MongoClient cli = new MongoClient(); 828 | // Database를 선택 829 | MongoDatabase db = cli.GetServer().GetDatabase("TestDB"); 830 | // 컬렉션 취득 831 | MongoCollection col = db.GetCollection("AddressBook"); 832 | public void Order_Where_Member_1() 833 | { 834 | var orderCollection = GetCollection(); // 컬렉션 취득을 함수화 835 | 836 | var orders = orderCollection.AsQueryable().Where( x => x.MemberId == 1 ).ToList(); 837 | 838 | orders.ForEach( x => 839 | { 840 | WriteOrder( x ); 841 | x.OrderDetails.ToList().ForEach( y => WriteOrderDetail( y ) ); 842 | } 843 | ); 844 | } 845 | ``` 846 | 847 | 848 | ####&& 849 | ``` 850 | var query = from e in collection.AsQueryable() 851 | where 852 | e.EmployeeStatus == Status.Active && 853 | e.Salary > 100000 854 | select e; 855 | 856 | // translates to: 857 | { EmployeeStatus : 1, Salary : { $gt : 100000 } } 858 | ``` 859 | 860 | 861 | ####문자열에서 일부 문자 찾기 862 | ``` 863 | var query = from e in collection.AsQueryable() 864 | where e.Name.Contains("oh") 865 | select e; 866 | 867 | // translates to: 868 | { nm: /oh/s } 869 | 870 | 871 | var query = from e in collection.AsQueryable() 872 | where e.Name.StartsWith("John") 873 | select e; 874 | 875 | // translates to: 876 | { nm: /^John/s } 877 | ``` 878 | 879 | 880 | ####string Length, IsNullOrEmpty 881 | ``` 882 | var query = from e in collection.AsQueryable() 883 | where e.Name.Length == 4 884 | select e; 885 | 886 | // translates to: 887 | { nm: /^.{4}$/s } 888 | 889 | 890 | var query = from e in collection.AsQueryable() 891 | where string.IsNullOrEmpty(e.Name) 892 | select e; 893 | 894 | // translates to: 895 | { $or : [ { nm: { $type : 10 } }, { nm: "" } ] } 896 | ``` 897 | 898 | 899 | ####string ToLower 900 | ``` 901 | var query = from e in collection.AsQueryable() 902 | where e.Name.ToLower() == "john macadam" 903 | select e; 904 | 905 | // translates to: 906 | { nm: /^john macadam$/is } 907 | ``` 908 | 909 | 910 | ####array element, Length 911 | ``` 912 | var query = from e in collection.AsQueryable() 913 | where e.Skills[0] == "Java" 914 | select e; 915 | 916 | // translates to: 917 | { "Skills.0" : "Java" } 918 | 919 | 920 | var query = from e in collection.AsQueryable() 921 | where e.Skills.Length == 3 922 | select e; 923 | 924 | // translates to: 925 | { Skills : { $size : 3 } } 926 | ``` 927 | 928 | 929 | ####dotted names 930 | ``` 931 | var query = from e in collection.AsQueryable() 932 | where e.Address.City == "Hoboken" 933 | select e; 934 | 935 | // translates to: 936 | { "Address.City" : "Hoboken" } 937 | ``` 938 | 939 | 940 | ####$in 941 | ``` 942 | var states = new [] { "NJ", "NY", "PA" }; 943 | var query = from e in collection.AsQueryable() 944 | where states.Contains(e.Address.State) 945 | select e; 946 | 947 | // translates to: 948 | { "Address.State" : { $in : [ "NJ", "NY", "PA" ] } } 949 | 950 | 951 | // alternative syntax using C#/.NET driver "In" method 952 | var query = from e in collection.AsQueryable() 953 | where e.Address.State.In(states) 954 | select e; 955 | ``` 956 | 957 | 958 | ####$in/$all with arrays 959 | ``` 960 | var desiredSkills = new [] { "Java", "C#" }; 961 | var query = from e in collection.AsQueryable() 962 | where e.Skills.ContainsAny(desiredSkills) 963 | select e; 964 | 965 | // translates to: 966 | { "Skills" : { $in : [ "Java", "C#" ] } } 967 | 968 | 969 | var query = from e in collection.AsQueryable() 970 | where e.Skills.ContainsAll(desiredSkills) 971 | select e; 972 | 973 | // translates to: 974 | { "Skills" : { $all : [ "Java", "C#" ] } } 975 | // note: ContainsAny and ContainsAll are defined by the C#/.NET 976 | driver and are not part of standard LINQ 977 | ``` 978 | 979 | 980 | ####$elemMatch 981 | ``` 982 | var query = from e in collection.AsQueryable() 983 | where 984 | e.Addresses.Any(a => 985 | a.City == "Hoboken" && 986 | a.State == "NJ") 987 | select e; 988 | 989 | // translates to: 990 | { "Addresses" : { $elemMatch : 991 | { City : "Hoboken", State : "NJ" } } } 992 | ``` 993 | 994 | 995 | ####Mixing LINQ with MongoDB queries 996 | ``` 997 | var query = from e in collection.AsQueryable() 998 | where 999 | e.Salary > 50000 && 1000 | Query.NotExists("EmployeeStatus").Inject() 1001 | select e; 1002 | 1003 | // translates to: 1004 | { 1005 | Salary : { $gt : 50000 }, 1006 | EmployeeStatus : { $exists : false } 1007 | } 1008 | ``` 1009 | 1010 | 1011 | 1012 | ###참고 문서 1013 | - What's new in the .NET Driver 1014 | http://www.slideshare.net/mongodb/webinar-whats-new-in-the-net-driver 1015 | - CSharp Driver LINQ Tutorial 1016 | http://docs.mongodb.org/ecosystem/tutorial/use-linq-queries-with-csharp-driver/ 1017 | 1018 | 1019 | 1020 | ###Error Code 1021 | http://www.mongodb.org/about/contributors/error-codes/ 1022 | -------------------------------------------------------------------------------- /MongoDBCSharpVer2.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ###MongoDB 공식 C# Driver 5 | - 1.x와 2.x 라이브러리가 많이 다름. 6 | - [2.0 드라이버 소개](https://www.mongodb.com/blog/post/introducing-20-net-driver) 7 | - [레퍼런스](http://mongodb.github.io/mongo-csharp-driver/2.0/reference/) 8 | - [온라인 도움 문서](http://api.mongodb.org/csharp/2.0/html/R_Project_CSharpDriverDocs.htm) 9 | - [Indexes.CreateOneAsync sample](http://qiita.com/SHUAI/items/f9479f2c1a09bbd7e36b) 10 | - [Find & FindAsync sample](http://qiita.com/SHUAI/items/ace6f6d3f08bb8dd79c5) 11 | 12 | 13 | ### collection 객체 얻기 14 | 15 | ``` 16 | public static IMongoCollection GetMongoDBCollectionVer2(string connectString, string dbName, string collectionName) 17 | { 18 | var mongoClient = new MongoClient(connectString); 19 | if (mongoClient == null) 20 | { 21 | return null; 22 | } 23 | 24 | var collection = mongoClient.GetDatabase(dbName).GetCollection(collectionName); 25 | return collection; 26 | } 27 | ``` 28 | 29 | 30 | ### Find 31 | #### 데이터 하나만 가져온다 32 | ``` 33 | try 34 | { 35 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 36 | 37 | // 기본으로는 Find 메소드는 없다. Find는 확장 메소드로 사용하고 싶다면 38 | //using MongoDB.Driver.Core.Misc; 39 | //using MongoDB.Driver; 40 | //을 선언해야 한다. 41 | 42 | // 첫 번째 값 또는 null 43 | var document = await collection.Find(x => x._id == "jacking").FirstOrDefaultAsync(); 44 | document.Dump(); 45 | } 46 | catch (Exception ex) 47 | { 48 | ex.Message.Dump(); 49 | } 50 | ``` 51 | 52 | #### BsonDocument를 사용한 조건 쿼리 53 | ``` 54 | try 55 | { 56 | var userID = "jacking"; 57 | int userLevel = 0; 58 | 59 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 60 | var filter = new BsonDocument("_id", userID); 61 | var documents = await collection.Find(filter).ToListAsync(); 62 | 63 | if (documents.Count > 0) 64 | { 65 | userLevel = documents[0]["Level"].AsInt32; 66 | } 67 | 68 | userLevel.Dump(); 69 | } 70 | catch (Exception ex) 71 | { 72 | ex.Message.Dump(); 73 | } 74 | ``` 75 | 76 | #### BsonDocument를 사용한 조건 쿼리 2 77 | ``` 78 | try 79 | { 80 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 81 | 82 | var filter = new BsonDocument("Level", new BsonDocument("$gte", 2)); 83 | var documents = await collection.Find(filter).ToListAsync(); 84 | documents.Dump(); 85 | } 86 | catch (Exception ex) 87 | { 88 | ex.Message.Dump(); 89 | } 90 | ``` 91 | 92 | #### BsonDocument를 사용한 조건 쿼리 3 93 | ``` 94 | try 95 | { 96 | // Builders를 사용할 때는 Collection은 BsonDocument를 사용해야 한다. 97 | 98 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 99 | 100 | var builder = Builders.Filter; 101 | var filter = builder.Gte("Level", 2) & builder.Eq("Money", 1000); 102 | var documents = await collection.Find(filter).ToListAsync(); 103 | 104 | var IDList = new List(); 105 | 106 | foreach (var document in documents) 107 | { 108 | IDList.Add(document["_id"].AsString); 109 | } 110 | 111 | IDList.Dump(); 112 | } 113 | catch (Exception ex) 114 | { 115 | ex.Message.Dump(); 116 | } 117 | ``` 118 | 119 | #### 클래스를 사용한 조건 쿼리 120 | ``` 121 | try 122 | { 123 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 124 | var documents = await collection.Find(x=> x.Level >= 2).ToListAsync(); 125 | documents.Dump(); 126 | } 127 | catch (Exception ex) 128 | { 129 | ex.Message.Dump(); 130 | } 131 | ``` 132 | 133 | #### 정렬 134 | ``` 135 | try 136 | { 137 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 138 | 139 | // 내림차순 140 | //var documents = await collection.Find(x=> x.Level >= 1).SortByDescending(d => d.Level).FirstOrDefaultAsync(); 141 | // or 142 | //var documents = await collection.Find(x=> x.Level >= 1).SortByDescending(d => d.Level).FirstOrDefaultAsync(); 143 | // or 144 | //var documents = await collection.Find(x=> x.Level >= 1).SortByDescending(d => d.Level).ToListAsync(); 145 | // or 조건 없이 146 | var documents = await collection.Find(x => true).SortByDescending(d => d.Level).ToListAsync(); 147 | documents.Dump(); 148 | } 149 | catch (Exception ex) 150 | { 151 | ex.Message.Dump(); 152 | } 153 | ``` 154 | 155 | #### 정렬 2 156 | ``` 157 | try 158 | { 159 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 160 | 161 | // 올림 차순 162 | //var documents = await collection.Find(new BsonDocument()).Sort(new BsonDocument("$Level", 1)).ToListAsync(); 163 | 164 | // 내림 차순 165 | //var documents = await collection.Find(new BsonDocument()).Sort(new BsonDocument("Level", -1)).ToListAsync(); 166 | // or 167 | var documents = await collection.Find(new BsonDocument()).Sort("{Level: -1}").ToListAsync(); 168 | documents.Dump(); 169 | } 170 | catch (Exception ex) 171 | { 172 | ex.Message.Dump(); 173 | } 174 | ``` 175 | 176 | #### 정렬 3 177 | ``` 178 | var sort = Builders.Sort.Ascending("borough").Ascending("address.zipcode"); 179 | var result = await collection.Find(filter).Sort(sort).ToListAsync(); 180 | ``` 181 | 182 | #### 특정 필드의 데이터만 가져오기 183 | ``` 184 | try 185 | { 186 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 187 | 188 | // Level만 189 | var documents = await collection.Find(new BsonDocument()).Project(BsonDocument.Parse("{Level:1}")).ToListAsync(); 190 | // Level, Money만 191 | //var documents = await collection.Find(new BsonDocument()).Project(BsonDocument.Parse("{Level:1, Money:1}")).ToListAsync(); 192 | 193 | documents.Dump(); 194 | } 195 | catch (Exception ex) 196 | { 197 | ex.Message.Dump(); 198 | } 199 | ``` 200 | 201 | #### 특정 필드를 가져오기 202 | ``` 203 | try 204 | { 205 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 206 | 207 | var projection = Builders.Projection.Include("Exp").Include("Level"); 208 | var documents = await collection.Find(x => true).Project(projection).ToListAsync(); 209 | documents.Dump(); 210 | } 211 | catch (Exception ex) 212 | { 213 | ex.Message.Dump(); 214 | } 215 | ``` 216 | 217 | #### 특정 필드를 제외한 데이터만 가져오기 218 | ``` 219 | try 220 | { 221 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 222 | 223 | // Level만 224 | var documents = await collection.Find(new BsonDocument()).Project(BsonDocument.Parse("{Level:0}")).ToListAsync(); 225 | documents.Dump(); 226 | } 227 | catch (Exception ex) 228 | { 229 | ex.Message.Dump(); 230 | } 231 | ``` 232 | 233 | #### Expression. 지정된 필드만, 필드는 다른 이름으로 234 | ``` 235 | try 236 | { 237 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 238 | 239 | var projection = Builders.Projection.Expression(x => new { X = x.Level, Y = x.Exp }); 240 | var documents = await collection.Find(x => true).Project(projection).ToListAsync(); 241 | documents.Dump(); 242 | } 243 | catch (Exception ex) 244 | { 245 | ex.Message.Dump(); 246 | } 247 | 248 | //var projection = Builders.Projection.Expression(x => new { X = x.X, Y = x.Y }); 249 | //var projection = Builders.Projection.Expression(x => new { Sum = x.X + x.Y }); 250 | //var projection = Builders.Projection.Expression(x => new { Avg = (x.X + x.Y) / 2 }); 251 | //var projection = Builders.Projection.Expression(x => (x.X + x.Y) / 2); 252 | 253 | // sort + projection + skip + limt 254 | try 255 | { 256 | //var userID = "jacking"; 257 | //int userLevel = 0; 258 | 259 | var projection = BsonDocument.Parse("{Level:1, Momey:1, Exp:1}"); 260 | var sort = BsonDocument.Parse("{Level:1}"); 261 | var options = new FindOptions 262 | { 263 | AllowPartialResults = true, 264 | BatchSize = 20, 265 | Comment = "funny", 266 | //CursorType = CursorType.TailableAwait, 267 | MaxTime = TimeSpan.FromSeconds(3), 268 | NoCursorTimeout = true 269 | }; 270 | 271 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 272 | var documents = collection.Find(x => x.Exp >= 0, options).Project(projection) 273 | .Sort(sort) 274 | .Limit(30) 275 | .Skip(0).ToListAsync(); 276 | 277 | documents.Dump(); 278 | } 279 | catch (Exception ex) 280 | { 281 | ex.Message.Dump(); 282 | } 283 | ``` 284 | 285 | #### Builders 사용 286 | ``` 287 | try 288 | { 289 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 290 | 291 | var builder = Builders.Filter; 292 | var filter = builder.Eq(x => x._id, "jacking") & builder.Lt(x => x.Money, 1100); 293 | // or 294 | //var filter = builder.Eq("X", 10) & builder.Lt("Y", 20); 295 | // or 296 | //var filter = builder.Eq("x", 10) & builder.Lt("y", 20); 297 | // or 298 | //var filter = Builders.Filter.Where(x => x._id == "jacking" && x.Money < 1100); 299 | 300 | // 첫 번째 값 또는 null 301 | var document = await collection.Find(filter).FirstOrDefaultAsync(); 302 | document.Dump(); 303 | } 304 | catch (Exception ex) 305 | { 306 | ex.Message.Dump(); 307 | } 308 | ``` 309 | 310 | #### 배열 요소 조건 검색 311 | ``` 312 | try 313 | { 314 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 315 | 316 | var filter = Builders.Filter.AnyGt(x => x.Costume, 0); 317 | var documents = await collection.Find(filter).ToListAsync(); 318 | documents.Dump(); 319 | } 320 | catch (Exception ex) 321 | { 322 | ex.Message.Dump(); 323 | } 324 | 325 | 326 | // 비동기로 검색 후 데이터를 비동기로 바로 사용 327 | var filter = new BsonDocument("x", new BsonDocument("$gte", 100)); 328 | await collection.Find(filter).ForEachAsync(async document => 329 | { 330 | await ProcessDocumentAsync(document); 331 | }); 332 | ``` 333 | 334 | #### FindAll 335 | ``` 336 | async Task FooAsync() 337 | { 338 | var list = await collection.Find(_ => true).ToListAsync(); 339 | } 340 | ``` 341 | 342 | #### FindOneAndReplaceAsync 343 | ``` 344 | try 345 | { 346 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 347 | 348 | var newData = new DBBasic() 349 | { 350 | _id = "jacking3", 351 | Money = 3333, 352 | Costume = new List(Enumerable.Repeat(0, 12)) 353 | }; 354 | 355 | // 변경 되기 이전 값을 반환한다. 실패하면 null 356 | var documents = await collection.FindOneAndReplaceAsync(x => x._id == "jacking5", newData); 357 | documents.Dump(); 358 | } 359 | catch (Exception ex) 360 | { 361 | ex.Message.Dump(); 362 | } 363 | ``` 364 | 365 | #### FindOneAndReplaceAsync 366 | ``` 367 | try 368 | { 369 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 370 | 371 | var filter = new BsonDocument("_id", "jacking3"); 372 | 373 | // _id와 Level 필드만 도큐먼트에 남게된다. 374 | var replacement = BsonDocument.Parse("{Level: 12}"); 375 | //var projection = BsonDocument.Parse("{x: 1}"); 376 | //var sort = BsonDocument.Parse("{a: -1}"); 377 | var options = new FindOneAndReplaceOptions() 378 | { 379 | IsUpsert = false, 380 | //Projection = projection, 381 | //ReturnDocument = returnDocument, 382 | //Sort = sort, 383 | MaxTime = TimeSpan.FromSeconds(2) 384 | }; 385 | 386 | var documents = await collection.FindOneAndReplaceAsync(filter, replacement, options, CancellationToken.None); 387 | documents.Dump(); 388 | } 389 | catch (Exception ex) 390 | { 391 | ex.Message.Dump(); 392 | } 393 | ``` 394 | 395 | #### FindOneAndUpdateAsync 396 | ``` 397 | try 398 | { 399 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 400 | 401 | var filter = new BsonDocument("_id", "jacking3"); 402 | var update = BsonDocument.Parse("{$set: {Level: 3}}"); 403 | //var projection = BsonDocument.Parse("{x: 1}"); 404 | //var sort = BsonDocument.Parse("{a: -1}"); 405 | var options = new FindOneAndUpdateOptions() 406 | { 407 | //IsUpsert = isUpsert, 408 | //Projection = projection, 409 | //ReturnDocument = returnDocument, 410 | //Sort = sort, 411 | MaxTime = TimeSpan.FromSeconds(2) 412 | }; 413 | 414 | 415 | var document = await collection.FindOneAndUpdateAsync(filter, update, options, CancellationToken.None); 416 | document.Dump(); 417 | } 418 | catch (Exception ex) 419 | { 420 | ex.Message.Dump(); 421 | } 422 | ``` 423 | 424 | 425 | ### Delete 426 | #### 삭제. 한번에 복수개를 지울 때는 DeleteManyAsync 427 | ``` 428 | try 429 | { 430 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 431 | 432 | var userID = "jacking4"; 433 | var result = await collection.DeleteOneAsync(x=> x._id == userID); 434 | result.Dump(); 435 | } 436 | catch (Exception ex) 437 | { 438 | ex.Message.Dump(); 439 | } 440 | ``` 441 | 442 | 443 | ### Insert 444 | #### 기본 445 | ``` 446 | try 447 | { 448 | var newData = new DBBasic() 449 | { 450 | _id = "jacking3", 451 | Level = 1, 452 | Exp = 0, 453 | Money = 1000, 454 | Costume = new List(Enumerable.Repeat(0, 12)), 455 | }; 456 | 457 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 458 | await collection.InsertOneAsync(newData); 459 | } 460 | catch(Exception ex) 461 | { 462 | ex.Message.Dump(); 463 | } 464 | ``` 465 | 466 | #### 복수의 데이터를 넣기 467 | ``` 468 | try 469 | { 470 | var newItemList = new List(); 471 | 472 | var itemIDList = new List() { 1001, 1002, 1003 }; 473 | int i = 0; 474 | foreach (var itemID in itemIDList) 475 | { 476 | ++i; 477 | 478 | var newData = new DBUserItem() 479 | { 480 | _id = DateTime.Now.Ticks + i, 481 | UserID = "jacking", 482 | ItemID = itemID, 483 | AcquireDateTime = DateTime.Now, 484 | }; 485 | 486 | newItemList.Add(newData); 487 | } 488 | 489 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Item"); 490 | await collection.InsertManyAsync(newItemList); 491 | } 492 | catch (Exception ex) 493 | { 494 | ex.Message.Dump(); 495 | } 496 | ``` 497 | 498 | #### 동적 기능 사용하기 499 | ``` 500 | try 501 | { 502 | dynamic person = new System.Dynamic.ExpandoObject(); 503 | person.FirstName = "Jane"; 504 | person.Age = 12; 505 | person.PetNames = new List { "Sherlock", "Watson" }; 506 | 507 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Persion"); 508 | await collection.InsertOneAsync(person); 509 | } 510 | catch (Exception ex) 511 | { 512 | ex.Message.Dump(); 513 | } 514 | ``` 515 | 516 | #### UTC 시간 보정해서 데이터 넣기 517 | ``` 518 | try 519 | { 520 | var newData = new DBTimeData() 521 | { 522 | CurTime = DateTime.Now.AddHours(9) 523 | }; 524 | 525 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "TimeData"); 526 | await collection.InsertOneAsync(newData); 527 | } 528 | catch(Exception ex) 529 | { 530 | ex.Message.Dump(); 531 | } 532 | ``` 533 | 534 | 535 | ### Update 536 | #### 기본 업데이트 537 | ``` 538 | // UpdateOneAsync 는 하나만, 복수는 UpdateManyAsync 539 | try 540 | { 541 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Skill"); 542 | 543 | var userID = "jacking"; 544 | 545 | var result = await collection.UpdateOneAsync(x => x._id == userID, 546 | Builders.Update.Set(x => x.Value, 14)); 547 | 548 | result.Dump(); 549 | // result.MatchedCount 가 1 보다 작으면 업데이트 한 것이 없음 550 | } 551 | catch (Exception ex) 552 | { 553 | ex.Message.Dump(); 554 | } 555 | ``` 556 | 557 | #### 도큐먼트의 내부 도큐먼트를 변경할 때 558 | ``` 559 | try 560 | { 561 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Skill"); 562 | 563 | var userID = "jacking"; 564 | int skillItemID = 1; 565 | var newInfo = new SkillItemInfo() { Value = 101 }; 566 | 567 | 568 | var filter = Builders.Filter.And(Builders.Filter.Eq(x => x._id, userID), 569 | Builders.Filter.ElemMatch(x => x.SkillItems, x => x.ID == skillItemID)); 570 | 571 | var update = Builders.Update.Set("SkillItems.$.Info", newInfo); 572 | //or 573 | //var update = Builders.Update.Set(x => x.SkillItems.ElementAt(-1).Info, newInfo); 574 | 575 | collection.UpdateOneAsync(filter, update); 576 | } 577 | catch (Exception ex) 578 | { 579 | ex.Message.Dump(); 580 | } 581 | ``` 582 | 583 | #### Replace 584 | ``` 585 | try 586 | { 587 | var collection = MyExtensions.GetMongoDBCollectionVer2("mongodb://172.20.60.221", "TestDB", "Basic"); 588 | 589 | var userID = "jacking"; 590 | var documents = await collection.Find(x=> x._id == userID).SingleAsync(); 591 | 592 | if( documents != null) 593 | { 594 | documents.Level = documents.Level + 3; 595 | var result = await collection.ReplaceOneAsync(x => x._id == documents._id, documents); 596 | result.Dump(); 597 | } 598 | else 599 | { 600 | Console.WriteLine("없음"); 601 | } 602 | } 603 | catch (Exception ex) 604 | { 605 | ex.Message.Dump(); 606 | } 607 | ``` 608 | ``` 609 | var tom = await collection.Find(x => x.Id == ObjectId.Parse("550c4aa98e59471bddf68eef")) 610 | .SingleAsync(); 611 | 612 | tom.Name = "Thomas"; 613 | tom.Age = 43; 614 | tom.Profession = "Hacker"; 615 | 616 | var result = await collection.ReplaceOneAsync(x => x.Id == tom.Id, tom); 617 | ``` 618 | 619 | 620 | 621 | 622 | *** 623 | 아래 내용 수정해야한다. 624 | ###접속 시 인증 625 | ``` 626 | // on the connection string 627 | var connectionString = "mongodb://user:pwd@localhost/?safe=true"; 628 | var server = MongoServer.Create(connectionString); 629 | 630 | // in code 631 | var cs = "mongodb:localhost"; 632 | MongoClient cli = new MongoClient(connectString); 633 | 634 | var settings = new MongoServerSettings(); 635 | var adminCredential = new MongoCredential("databaseName", "user", "pwd"); 636 | settings.Credentials.Add(adminCredential); 637 | ``` 638 | 639 | 640 | 641 | ###옵션 설정하기 642 | - connection pool 크기 설정 643 | 644 | ``` 645 | // on the connection string 646 | ConnectString="mongodb://172.20.60.221:27018/?maxPoolSize=256" 647 | 648 | // in code 649 | MongoClientSettings.MaxConnectionPoolSize 650 | MongoClientSettings.MinConnectionPoolSize Property 651 | ``` 652 | 653 | 654 | 655 | ###직렬화 656 | 657 | ``` 658 | class Person 659 | { 660 | [BsonElement("fn")] 661 | public string FirstName { get; set; } 662 | 663 | [BsonElement("fn")] 664 | public string LastName { get; set; } 665 | } 666 | 667 | public class GroceryList : MongoEntity 668 | { 669 | public FacebookList Owner { get; set; } 670 | [BsonIgnore] 671 | public bool IsOwner { get; set; } 672 | } 673 | ``` 674 | 675 | 676 | ###시간 사용 677 | ####MongoDB에서 사용할 수 있는 현재 시간 변환. 678 | MongoDB는 유니버셜 시간대를 사용하고 있으므로 시간을 그냥 사용하면 현재 시간 -9 시간으로 변환되어 버린다. 679 | ``` 680 | public static DateTime GetLocalTime() 681 | { 682 | string strCurDateTime = DateTime.Now.ToString("yyyyMMddHHmmss"); 683 | IFormatProvider culture = new System.Globalization.CultureInfo("", true); 684 | 685 | DateTime LocalDateTime = DateTime.ParseExact(strCurDateTime, "yyyyMMddHHmmss", culture, System.Globalization.DateTimeStyles.AssumeUniversal); 686 | 687 | return LocalDateTime; 688 | } 689 | ``` 690 | 691 | ####입력 692 | - 201308011121 라는 문자열로 DateTime 객체를 만든다. 693 | - 중요: MongoDB는 UTC date 타임대를 사용하므로 694 | 695 | ``` 696 | System.Globalization.DateTimeStyles.AssumeUniversal 로 조정한다 697 | IFormatProvider culture = new System.Globalization.CultureInfo("", true); 698 | DateTime date = DateTime.ParseExact(date_time, "yyyyMMddHHmm", culture, System.Globalization.DateTimeStyles.AssumeUniversal); 699 | 700 | 701 | var collection = BasicLogDB.GetCollection("Login"); 702 | 703 | BsonDocument data = new BsonDocument() 704 | { 705 | {"ID", id}, 706 | {"UniqNum", UniqueNumber}, 707 | {"date", date} 708 | }; 709 | 710 | await collection.InsertOneAsync(data); 711 | ``` 712 | 713 | 714 | ###예제 Insert 715 | ####비동기로 하나만 추가 716 | ``` 717 | using MongoDB.Bson; 718 | using MongoDB.Driver; 719 | using MongoDB.Driver.Builders; 720 | 721 | MongoClient cli = new MongoClient(textBoxAddress.Text); 722 | MongoDatabase testdb = cli.GetServer().GetDatabase("test"); 723 | 724 | MongoCollection Customers = testdb.GetCollection("Account"); 725 | 726 | try 727 | { 728 | for (int i = 0; i < Count; ++i) 729 | { 730 | BsonDocument data = new BsonDocument() 731 | { 732 | {"ID", string.Format("{0}{1}",textBoxPreFix.Text, (StartIndex+i).ToString())}, 733 | {"PW", "1111"} 734 | }; 735 | 736 | var result = Customers.Insert(data); 737 | 738 | if(result.Ok == false) 739 | return false; 740 | } 741 | } 742 | catch (Exception err) 743 | { 744 | MessageBox.Show(err.ToString()); 745 | } 746 | ``` 747 | 748 | ####제너릭 데이터를 사용한 추가 749 | ``` 750 | ... 751 | 752 | userInfo = new UserInfo 753 | { 754 | UserIndex = 1, 755 | ID = id, 756 | PW = pw, 757 | }; 758 | 759 | var result = Coll.Insert(userInfo); 760 | 761 | if (result.Ok == false) 762 | { 763 | return null; 764 | } 765 | ``` 766 | 767 | ####다수의 값을 한번에 추가할 때 InsertBatck 768 | - 복사할 곳(dest)에 복사대상(source)와 같은 index를 가진 것이 있으면 안 된다. 769 | 770 | ``` 771 | MongoCollection books; 772 | BsonDocument[] batch = { 773 | new BsonDocument { 774 | { "author", "Kurt Vonnegut" }, 775 | { "title", "Cat's Cradle" } 776 | }, 777 | new BsonDocument { 778 | { "author", "Kurt Vonnegut" }, 779 | { "title", "Slaughterhouse-Five" } 780 | } 781 | }; 782 | books.InsertBatch(batch); 783 | var squadList = new List(); 784 | squadList.Add(new CharData 785 | { 786 | UserIndex = userIndex, 787 | Slot = 0, 788 | }); 789 | squadList.Add(new CharData 790 | { 791 | UserIndex = userIndex, 792 | Slot = 1, 793 | }); 794 | 795 | var result = Coll.InsertBatch(squadList); 796 | 797 | if (result.Count() != 1) 798 | { 799 | return false; 800 | } 801 | ``` 802 | 803 | 804 | ###문자열을 ObjectId로 변환하기 805 | ``` 806 | var query_id = Query.EQ("_id", ObjectId.Parse("50ed4e7d5baffd13a44d0153")); 807 | // 몽고디비 툴에서 검색할 때 808 | db.Users.find( {_id:ObjectId("546173b07c935c15942aa233")}) 809 | ``` 810 | 811 | 812 | 813 | ###예제 Select 814 | ####하나만 반환 815 | - 검색된 것이 없을 때는 null 반환. 그러나 하나 이상 있을 때는 예외 발생 816 | 817 | ``` 818 | public static bool Auth(string id, string pw) 819 | { 820 | try 821 | { 822 | MongoClient cli = new MongoClient("mongodb://172.20.60.221"); 823 | MongoDatabase database = cli.GetServer().GetDatabase("test"); 824 | var Accounts = database.GetCollection("Account"); 825 | 826 | IMongoQuery query = Query.EQ("ID", id); 827 | var result = Accounts.Find(query).SingleOrDefault(); 828 | 829 | if (result == null) 830 | { 831 | return false; 832 | } 833 | 834 | if (result["PW"] != pw) 835 | { 836 | return false; 837 | } 838 | } 839 | catch(Exception ex) 840 | { 841 | return false; 842 | } 843 | 844 | return true; 845 | } 846 | ``` 847 | 848 | ####여러개 반환 849 | ``` 850 | IMongoQuery query = Query.EQ("version", version); 851 | var results = ItemInfo.Find(query); 852 | 853 | 854 | List itemlist = new List(); 855 | 856 | foreach (var iteminfo in results) 857 | { 858 | var item = new ItemInfo 859 | { 860 | version = version, 861 | ID = iteminfo["ID"].AsInt32, 862 | name = iteminfo["name"].AsString, 863 | Lv = iteminfo["Lv"].AsInt32 864 | }; 865 | 866 | itemlist.Add(item); 867 | } 868 | // 869 | public class ItemInfo 870 | { 871 | public int version; 872 | public int ID; 873 | public string name; 874 | public int Lv; 875 | } 876 | ``` 877 | 878 | ####Where절 사용 879 | ``` 880 | Query.Where(d => d.EmployeeNumber == 1234) 881 | Query.Where(d => d.Name == "John Doe") 882 | Query.Where(d => d.EmployeeStatus != Status.Active) 883 | Query.Where(d => d.Salary > 100000) 884 | ``` 885 | 886 | ####복합 쿼리 887 | ``` 888 | var query = Query.GTE("x", 1).LTE(3); 889 | // becomes 890 | var query = Query.And(Query.GTE("x", 1), Query.LTE("x", 3)); 891 | 892 | var query = Query.Not("x").GT(1); 893 | // becomes 894 | var query = Query.Not(Query.GT("x", 1)); 895 | 896 | var query = Query.Exists("x", true); 897 | // becomes 898 | var query = Query.Exists("x"); 899 | 900 | var query = Query.Exists("x", false); 901 | // becomes 902 | var query = Query.NotExists("x"); 903 | ``` 904 | 905 | ####해당 collection 모든 데이터 가져오기 906 | ``` 907 | List lstAccount = new List(); 908 | 909 | MongoClient cli = new MongoClient("mongodb://172.20.60.221"); 910 | MongoDatabase database = cli.GetServer().GetDatabase("WebTest"); 911 | var Accounts = database.GetCollection("Account"); 912 | 913 | // query문 없이 FindAll 사용, 해당 collection에 모든 데이터를 가져올 수 있다. 914 | var result = Accounts.FindAll(); 915 | 916 | foreach (var AccountInfo in result) 917 | { 918 | var Account = new AccountData 919 | { 920 | AccountID = AccountInfo["ID"].AsString, 921 | PassWord = AccountInfo["PW"].AsDouble 922 | }; 923 | } 924 | return lstAccount; 925 | ``` 926 | 927 | ###First, Last 928 | - First는 제일 첫 번째, Last는 제일 마지막 도큐먼트 반환한다. 그러나 컬렉션에 도큐먼트가 하나도 없는 경우 예외가 발생한다. 929 | - 그래서 안전하게 사용하고 싶다면 FirstOrDefault, LastOrDefult를 사용하는 것이 좋다. 930 | - Default로 만들기 위해 델리게이트 지정을 안하면 null이 반환된다 931 | 932 | 933 | ###예제 Update, Delete 934 | ``` 935 | // http://www.csharpstudy.com/Tips/Tips-mongodb.aspx 936 | // Mongo DB를 위한 Connection String 937 | string connString = "mongodb://localhost"; 938 | 939 | // MongoClient 클라이언트 객체 생성 940 | MongoClient cli = new MongoClient(connString); 941 | 942 | // testdb 라는 데이타베이스 가져오기 943 | // 만약 해당 DB 없으면 Collection 생성시 새로 생성함 944 | MongoDatabase testdb = cli.GetServer().GetDatabase("testdb"); 945 | 946 | // testdb 안에 Customers 라는 컬렉션(일종의 테이블) 947 | // 가져오기. 만약 없으면 새로 생성. 948 | var customers = testdb.GetCollection("Customers"); 949 | 950 | // INSERT - 컬렉션 객체의 Insert() 메서드 호출 951 | // Insert시 _id 라는 자동으로 ObjectID 생성 952 | // 이 _id는 해당 다큐먼트는 나타는 키. 953 | Customer cust1 = new Customer { Name = "Kim", Age = 30 }; 954 | customers.Insert(cust1); 955 | ObjectId id = cust1.Id; 956 | 957 | // SELECT - id로 검색 958 | IMongoQuery query = Query.EQ("_id", id); 959 | var result = customers.Find(query).SingleOrDefault(); 960 | if (result != null) 961 | { 962 | Console.WriteLine(result.ToString()); 963 | } 964 | 965 | // UPDATE 966 | // Save() = 전체 다큐먼트 갱신. 967 | // Update() = 부분 수정 968 | cust1.Age = 31; 969 | customers.Save(cust1); 970 | 971 | // DELETE 972 | var qry = Query.EQ("_id", id); 973 | customers.Remove(qry); 974 | ``` 975 | 976 | 데이터가 없으면 추가하고, 있다면 업데이트 하기 977 | ``` 978 | static void SaveServerHeartBeatInfo_Callback(Object state) 979 | { 980 | try 981 | { 982 | ... 983 | var collection = database.GetCollection("컬렉션"); 984 | var findData = collection.FindOne(MongoDB.Driver.Builders.Query.EQ("name", id)); 985 | 986 | if (findData == null) 987 | { 988 | var saveData = new SAVE_DATA 989 | { 990 | Name = id, 991 | value = 1000 992 | }; 993 | 994 | collection.Save(saveData); 995 | } 996 | else 997 | { 998 | findData.value = 1001; 999 | collection.Save(findData); 1000 | } 1001 | } 1002 | catch (Exception ex) 1003 | { 1004 | } 1005 | } 1006 | ``` 1007 | 1008 | 1009 | ###예제 FindAndModify 1010 | ``` 1011 | var modifyArgs = new MongoDB.Driver.FindAndModifyArgs() 1012 | { 1013 | Query = Query.EQ("_id", objID), 1014 | Update = Update.Set("MaxBuild", maxBuild), 1015 | Fields = Fields.Include("MaxBuild"), // 이걸 지정하지 않으면 모든 필드의 값을 가져온다. 1016 | SortBy = SortBy.Null, 1017 | VersionReturned = MongoDB.Driver.FindAndModifyDocumentVersion.Modified, // 변경된 값을 가져온다. 1018 | Upsert = false, // 없으면 추가하지 않는다 1019 | }; 1020 | 1021 | var newResult = collection.FindAndModify(modifyArgs); 1022 | 1023 | // 검색 실패이면 null 1024 | if (newResult.ModifiedDocument == null) 1025 | { 1026 | return false; 1027 | } 1028 | 1029 | return true; 1030 | ``` 1031 | 1032 | 1033 | 1034 | ###증분으로 업데이트 하기 1035 | ``` 1036 | var modifyArgs = new MongoDB.Driver.FindAndModifyArgs() 1037 | { 1038 | Query = Query.EQ("_id", objID), 1039 | Update = Update.Inc("Money", change), 1040 | Fields = Fields.Include("Money"), 1041 | SortBy = SortBy.Null, 1042 | VersionReturned = MongoDB.Driver.FindAndModifyDocumentVersion.Modified, 1043 | Upsert = false, 1044 | }; 1045 | ``` 1046 | 1047 | 1048 | 1049 | ###복수 데이터 일괄 Update 1050 | ``` 1051 | var ub = new UpdateBuilder(); 1052 | ub.Set("Money", inputData.Money); 1053 | ub.Set("Exp", inputData.Exp); 1054 | ub.Set("Level", inputData.Level); 1055 | collection.Update(Query.EQ("UserID", inputData.UserID), ub); 1056 | ``` 1057 | 1058 | 1059 | 1060 | ###특정 필드 제외, 특정 필드만 쿼리하기 1061 | 특정 필드 제외 1062 | ``` 1063 | MongoClient cli = new MongoClient(DB_ConnectString); 1064 | MongoDatabase db = cli.GetServer().GetDatabase(BasicLogDatabaseName); 1065 | var UniqueNumberCol = db.GetCollection("UniqueNumber"); 1066 | 1067 | // _id 필드만 제외하고 모든 필드 데이터를 가져온다 1068 | var newResult = UniqueNumberCol.FindAll().SetFields(Fields.Exclude("_id")); 1069 | ``` 1070 | 1071 | 특정 필드만 가져오기 1072 | ``` 1073 | MongoClient cli = new MongoClient(DB_ConnectString); 1074 | MongoDatabase db = cli.GetServer().GetDatabase(BasicLogDatabaseName); 1075 | var UniqueNumberCol = db.GetCollection("UniqueNumber"); 1076 | 1077 | // money, level 필드 데이터만 가져온다 1078 | var newResult = UniqueNumberCol.FindAll().SetFields(Fields.include("money", "level")); 1079 | ``` 1080 | 1081 | 1082 | 1083 | ###날짜 쿼리 1084 | - 특정날짜의 데이터 개수 알아내기 1085 | - 시간은 mongoDB에서 자동으로 ISODate로 변경한다. 단 mongoDB에 있는 시간을 애플리케이션에서 사용할 때는 LocalDateTime으로 변경해야 OS의 시간과 일치한다. 1086 | - DB에 저장된 시간 데이터를 로딩할 때 DateTime.MinValue로 저장된 값은 ToLocalTime()으로 변환하지 않는다. 변환하면 MinValue와 다른 값이 된다 1087 | 1088 | ``` 1089 | // 어제 날짜 1090 | dateTime = DateTime.Now.AddDays(-1); 1091 | // 0시로 만들기 위해서 1092 | DateTime dateTime2 = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day); 1093 | var count = DBWork.DBDataMining.DailyNewUserStatistics(db, dateTime2); 1094 | 1095 | static public long DailyNewUserStatistics(MongoDBLib dbLib, DateTime dateTime) 1096 | { 1097 | var collection = dbLib.BasicLogDB.GetCollection("NewUser"); 1098 | var query = Query.And(Query.GTE("date", dateTime), Query.LTE("date", dateTime.AddDays(1)); 1099 | var count = collection.Find(query).Count(); 1100 | return count; 1101 | } 1102 | ``` 1103 | 1104 | 1105 | ###중복 제외 1106 | ``` 1107 | //{ 1108 | // "_id" : ObjectId("5209d0507dbe2af068a42aec"), 1109 | // "ID" : "jacking75", 1110 | // "Uniq" : 5, 1111 | // "date" : ISODate("2013-08-12T06:21:04Z") 1112 | //} 1113 | 1114 | DateTime datetime = MongoDBLib.StringToDateTime(yyyyMMddHHmm); 1115 | 1116 | // 로그인한 총 수를 얻는다 1117 | var collection = dbLib.BasicLogDB.GetCollection("LoginUser"); 1118 | var query = Query.And(Query.GTE("date", datetime), Query.LTE("date", datetime.AddDays(1))); 1119 | 1120 | // ID 필드 값 중 중복된 것을 제외하고 개수를 구한다 1121 | var UniqueLoginUserCount = collection.Distinct("ID", query).Count(); 1122 | ``` 1123 | 1124 | 1125 | 1126 | ###배열 추가 1127 | 데이터가 배열인 경우 1128 | ``` 1129 | var mongoClient = MongoDBLib.GetGameClient(MongoDBLib.GAME_DATABASE, userIndex); 1130 | 1131 | var database = mongoClient.GetServer().GetDatabase(MongoDBLib.GAME_DATABASE); 1132 | var collection = database.GetCollection(MongoDBLib.CLEARED_STAGE_LIST_COLLECTION); 1133 | 1134 | var result = collection.Update(Query.EQ("UserIndex", userIndex), Update.PushWrapped("StageIDList", stageID)); 1135 | isResult = result.UpdatedExisting; 1136 | ``` 1137 | 1138 | List 자료구조를 추가하기 1139 | ``` 1140 | int[] defaultValue = {0, 0, 0, 0, 0, 0, 0, 0}; 1141 | List aaa = new List(defaultValue); 1142 | 1143 | 1144 | var mongoClient = MongoDBLib.GetGameClient(); 1145 | MongoDatabase db = mongoClient.GetServer().GetDatabase("GAME_DATABASE"); 1146 | var Coll = db.GetCollection("collection"); 1147 | 1148 | BsonDocument data = new BsonDocument() 1149 | { 1150 | {"UserIndex", userIndex}, 1151 | {"Squard1", new BsonArray(aaa)}, 1152 | {"Squard2", new BsonArray(aaa)}, 1153 | {"Squard3", new BsonArray(aaa)}, 1154 | }; 1155 | int[] 기본값 = { 0, 0, 0, 0, 0, 0, 0, 0 }; 1156 | 1157 | var Coll = db.GetCollection(MongoDBLib.CHARACTER_SQUARD_COLLECTION); 1158 | 1159 | var squadList = new List(); 1160 | squadList.Add(new CharInfo 1161 | { 1162 | UserIndex = userIndex, 1163 | ItemIDs = 기본값.ToList(), 1164 | }); 1165 | squadList.Add(new CharInfo 1166 | { 1167 | UserIndex = userIndex, 1168 | ItemIDs = 기본값.ToList(), 1169 | }); 1170 | squadList.Add(new CharInfo 1171 | { 1172 | UserIndex = userIndex, 1173 | ItemIDs = 기본값.ToList(), 1174 | }); 1175 | 1176 | var result = Coll.InsertBatch(squadList); 1177 | 1178 | if (result.Count() != 1) 1179 | { 1180 | return false; 1181 | } 1182 | ``` 1183 | 1184 | 1185 | 1186 | ###배열 전체 업데이트 1187 | ``` 1188 | List usePosList; 1189 | Update = Update.Set("UseBPosList", new BsonArray(usePosList)) 1190 | ``` 1191 | 1192 | 1193 | 1194 | ###배열의 특정 요소만 업데이트 1195 | ``` 1196 | var aValue = new AA(); 1197 | 1198 | // AList의 1번 인덱스(두번째 위치)의 값을 바꾼다. 1199 | var query = Query.And(Query.EQ("UserID", userID), Query.EQ("Type", type)); 1200 | var update = Update.Set("AList." + 1, new BsonDocumentWrapper(aValue)); 1201 | 1202 | collection.Update(query, update); 1203 | ``` 1204 | 1205 | 1206 | 1207 | ###BSonDocument에서 배열 데이터 읽기 1208 | ``` 1209 | // 도큐먼트 1210 | //{ 1211 | // "Cash" : 100, 1212 | // "UseList" : [ false, false, false ], 1213 | //} 1214 | 1215 | var dataList = collection.Find(query); 1216 | 1217 | foreach (var data in dataList) 1218 | { 1219 | returnValue.Cash = data["Cash"].AsInt32; 1220 | returnValue.UseList = data["UseBPosList"].AsBsonArray.Select(p => p.AsBoolean).ToList(); 1221 | } 1222 | ``` 1223 | 1224 | 1225 | 1226 | ###skip & limit 1227 | ``` 1228 | Console.WriteLine(collection.Find(query).SetSkip(0).SetLimit(1).Size()); 1229 | ``` 1230 | 1231 | 1232 | 1233 | ###제일 마지막 레코드 가져오기 1234 | ``` 1235 | ... 1236 | MongoCollection table = db.GetCollection("Collection"); 1237 | var tableCount = (int)table.Count(); 1238 | 1239 | var skipCount = tableCount - 1; 1240 | var result = table.FindAll().SetSkip(skipCount); 1241 | 1242 | // result.Size() == 1 이면 제일 마지막 것만 가져온 것 이다. 1243 | ``` 1244 | 1245 | 1246 | 1247 | ###SP 실행 1248 | SP(저장프로시저) 코드를 직접 사용 1249 | ``` 1250 | var mongoClient = MongoDBLib.GetAccountClient(); 1251 | var database = mongoClient.GetServer().GetDatabase(MongoDBLib.ACCOUNT_DATABASE); 1252 | 1253 | BsonValue bv1 = database.Eval("function(x, y) { return x + y; }", x, y); 1254 | return (int)bv1.AsDouble; 1255 | ``` 1256 | 1257 | 몽고DB에 저장된 SP를 가져와서 실행 1258 | ``` 1259 | // 몽고DB 데이터베이스의 Functions에 TestSumSP라는 이름의 SP("function(x, y) { return x + y; }")를 만들어 놓음 1260 | var mongoClient = MongoDBLib.GetAccountClient(); 1261 | var database = mongoClient.GetServer().GetDatabase(MongoDBLib.ACCOUNT_DATABASE); 1262 | 1263 | BsonValue bv = database.Eval("TestSumSP", x, y); 1264 | BsonValue bv1 = database.Eval(bv.AsBsonJavaScript.Code, x, y); 1265 | return (int)bv1.AsDouble; 1266 | ``` 1267 | 1268 | 1269 | 1270 | ###SP 호출로 데이터 얻기 1271 | ``` 1272 | static string SP_GET_USER = @"function(userID, companyName) 1273 | { 1274 | var cursor = db.User.find( {$or:[{Name: companyName}, {ID: userID}]} ) 1275 | var hasData = cursor.hasNext() ? cursor.next() : null; 1276 | return hasData; 1277 | }"; 1278 | public static bool GetUser(string userID, string name) 1279 | { 1280 | bool result = false; 1281 | 1282 | try 1283 | { 1284 | var mongoClient = MongoDBLib.GetAccountClient(); 1285 | MongoDatabase db = mongoClient.GetServer().GetDatabase("AccountDB"); 1286 | BsonValue bv = db.Eval(SP_GET_USER, userID, name); 1287 | ... 1288 | 1289 | result = true; 1290 | } 1291 | catch (Exception ex) 1292 | { 1293 | return false; 1294 | } 1295 | 1296 | return result; 1297 | } 1298 | ``` 1299 | 1300 | 1301 | 1302 | ###중복 금지 1303 | - 인덱스 사용. 컬렉션에서 중복되면 안되는 필드에 인덱스(유니크)를 걸어서 중복으로 추가되지 않도록 한다. 1304 | C#에서 위와 같은 이유로(데이터 중복에 의해) 추가가 실패하면 예외가 발생한다. 1305 | - SP 사용 1306 | 1307 | ``` 1308 | static string SP_ADD_USER = @"function(userID, companyName) 1309 | { 1310 | var cursor = db.User.find( {$or:[{Name: companyName}, {ID: userID}]} ) 1311 | var hasData = cursor.hasNext() ? cursor.next() : null; 1312 | if(hasData) 1313 | { 1314 | return false; 1315 | } 1316 | 1317 | db.User.insert({ ID:userID, Name:companyName }) 1318 | return true; 1319 | }"; 1320 | public static bool AddUser(UserInfo userInfo) 1321 | { 1322 | bool result = false; 1323 | 1324 | try 1325 | { 1326 | var mongoClient = MongoDBLib.GetAccountClient(); 1327 | MongoDatabase db = mongoClient.GetServer().GetDatabase("AccountDB"); 1328 | BsonValue bv = db.Eval(SP_ADD_USER, userInfo.ID, userInfo.Name); 1329 | result = bv.AsBoolean; 1330 | } 1331 | catch (Exception ex) 1332 | { 1333 | return false; 1334 | } 1335 | 1336 | return result; 1337 | } 1338 | ``` 1339 | 1340 | ###정렬 1341 | - 데이터 개수가 많고 정렬한 데이터를 각각 업데이트 해야 한다면 MongoDB가 아닌 프로그램의 메모리 상에서 직접 정렬하는 것이 좋다. 1342 | - MongoDB가 느린 이유는 정렬자체 보다는 정렬 후 업데이트를 위해서 문서 하나하나를 업데이트 해야 하는 비용이 비싸기 때문이다. 1343 | - 업데이트라서 InsertBatch를 사용할 수 없어서 업데이트에 많은 비용이 소비된다. 1344 | - 그래서 프로그램에서 DB의 데이터를 가져온 후 직접 정렬한 후 기존 컬렉션의 데이터를 지우고 InserBatch로 새로 데이터를 넣는 것이 훨씬 더 좋다 1345 | - 정렬에 제한이 있다. 정렬할 데이터가 메모리 상에 32MB를 넘으면 안 된다. 그래서 정렬에 사용되는 필드는 모두 인덱스에 걸어야 한다. 1346 | 1347 | ``` 1348 | // 정렬 조건 TotalScore가 큰 수, Level이 큰 수, UID가 작은 수 1349 | // 복합 인덱스를 건다 db.WeekTotalNetProfit.ensureIndex({ TotalScore: -1, Level: -1, UID: 1 }) 1350 | public class DBUserWeekTotalNetProfit 1351 | { 1352 | public string _id; 1353 | public int Level; 1354 | public Int64 UID; 1355 | public Int64 TotalScore; 1356 | public int TotalTurn; 1357 | public int PrevOrder; // 전날 랭킹 순위 1358 | public int Order; // 순위 1359 | } 1360 | 1361 | try 1362 | { 1363 | var sortBy = SortBy.Descending(m => m.TotalScore).Descending(m => m.Level).Ascending(m => m.UID); 1364 | var userDataSources = MongoDBLib.GetUserWeekTotalNetProfitCollection(); 1365 | 1366 | int ord = 0; 1367 | foreach (var userDataSource in userDataSources.FindAll().SetSortOrder(sortBy)) 1368 | { 1369 | ord++; 1370 | userDataSource.PrevOrder = userDataSource.Order; 1371 | userDataSource.Order = ord; 1372 | userDataSources.Save(userDataSource); 1373 | } 1374 | } 1375 | catch (Exception ex) 1376 | { 1377 | } 1378 | ``` 1379 | 1380 | ``` 1381 | // BSonDocument 사용 시 1382 | var dbCollection = Collection(); 1383 | var dataList = dbCollection.FindAll().SetSortOrder(SortBy.Descending("TotalScore")); 1384 | ``` 1385 | 1386 | 1387 | ###컬렉션 복사 1388 | ``` 1389 | var sourceCollection = MongoDBLib.GetUserWeekTotalNetProfitCollection(); 1390 | var resultCollection = MongoDBLib.GetUserWeekTotalNetProfitResultCollection(); 1391 | 1392 | resultCollection.RemoveAll(); 1393 | resultCollection.InsertBatch(sourceCollection.FindAll()); 1394 | ``` 1395 | 1396 | 1397 | ###LINQ 1398 | - (일어)mongoDB에서도 LINQ를 사용하자 1399 | http://cerberus1974.hateblo.jp/entry/2012/12/13/000245 1400 | 1401 | ####기본 1402 | ``` 1403 | MongoDB.Driver 1404 | MongoDB.Driver.Builders 1405 | MongoDB.Driver.Linq 1406 | MongoDB.Bson 1407 | MongoDB.Bson.Serialization.Attributes 1408 | [BsonIgnoreExtraElements] 1409 | public class AddressEntry 1410 | { 1411 | [BsonId] 1412 | public BsonObjectId _id { get; set;} 1413 | public string Name { get; set; } 1414 | public DateTime Birthday { get; set; } 1415 | public List EmailAddrs { get; set; } 1416 | 1417 | [BsonIgnore] 1418 | public string Detail { get; set; } // 맵핑하지 않는다 1419 | } 1420 | 1421 | [BsonIgnoreExtraElements] 1422 | public class Email 1423 | { 1424 | public string DisplayName { get; set; } 1425 | public string MailAddress { get; set; } 1426 | } 1427 | 1428 | 1429 | // MongoDB에 접속 1430 | MongoClient cli = new MongoClient(); 1431 | // Database를 선택 1432 | MongoDatabase db = cli.GetServer().GetDatabase("TestDB"); 1433 | // 컬렉션 취득 1434 | MongoCollection col = db.GetCollection("AddressBook"); 1435 | public void Order_Where_Member_1() 1436 | { 1437 | var orderCollection = GetCollection(); // 컬렉션 취득을 함수화 1438 | 1439 | var orders = orderCollection.AsQueryable().Where( x => x.MemberId == 1 ).ToList(); 1440 | 1441 | orders.ForEach( x => 1442 | { 1443 | WriteOrder( x ); 1444 | x.OrderDetails.ToList().ForEach( y => WriteOrderDetail( y ) ); 1445 | } 1446 | ); 1447 | } 1448 | ``` 1449 | 1450 | 1451 | ####&& 1452 | ``` 1453 | var query = from e in collection.AsQueryable() 1454 | where 1455 | e.EmployeeStatus == Status.Active && 1456 | e.Salary > 100000 1457 | select e; 1458 | 1459 | // translates to: 1460 | { EmployeeStatus : 1, Salary : { $gt : 100000 } } 1461 | ``` 1462 | 1463 | 1464 | ####문자열에서 일부 문자 찾기 1465 | ``` 1466 | var query = from e in collection.AsQueryable() 1467 | where e.Name.Contains("oh") 1468 | select e; 1469 | 1470 | // translates to: 1471 | { nm: /oh/s } 1472 | 1473 | 1474 | var query = from e in collection.AsQueryable() 1475 | where e.Name.StartsWith("John") 1476 | select e; 1477 | 1478 | // translates to: 1479 | { nm: /^John/s } 1480 | ``` 1481 | 1482 | 1483 | ####string Length, IsNullOrEmpty 1484 | ``` 1485 | var query = from e in collection.AsQueryable() 1486 | where e.Name.Length == 4 1487 | select e; 1488 | 1489 | // translates to: 1490 | { nm: /^.{4}$/s } 1491 | 1492 | 1493 | var query = from e in collection.AsQueryable() 1494 | where string.IsNullOrEmpty(e.Name) 1495 | select e; 1496 | 1497 | // translates to: 1498 | { $or : [ { nm: { $type : 10 } }, { nm: "" } ] } 1499 | ``` 1500 | 1501 | 1502 | ####string ToLower 1503 | ``` 1504 | var query = from e in collection.AsQueryable() 1505 | where e.Name.ToLower() == "john macadam" 1506 | select e; 1507 | 1508 | // translates to: 1509 | { nm: /^john macadam$/is } 1510 | ``` 1511 | 1512 | 1513 | ####array element, Length 1514 | ``` 1515 | var query = from e in collection.AsQueryable() 1516 | where e.Skills[0] == "Java" 1517 | select e; 1518 | 1519 | // translates to: 1520 | { "Skills.0" : "Java" } 1521 | 1522 | 1523 | var query = from e in collection.AsQueryable() 1524 | where e.Skills.Length == 3 1525 | select e; 1526 | 1527 | // translates to: 1528 | { Skills : { $size : 3 } } 1529 | ``` 1530 | 1531 | 1532 | ####dotted names 1533 | ``` 1534 | var query = from e in collection.AsQueryable() 1535 | where e.Address.City == "Hoboken" 1536 | select e; 1537 | 1538 | // translates to: 1539 | { "Address.City" : "Hoboken" } 1540 | ``` 1541 | 1542 | 1543 | ####$in 1544 | ``` 1545 | var states = new [] { "NJ", "NY", "PA" }; 1546 | var query = from e in collection.AsQueryable() 1547 | where states.Contains(e.Address.State) 1548 | select e; 1549 | 1550 | // translates to: 1551 | { "Address.State" : { $in : [ "NJ", "NY", "PA" ] } } 1552 | 1553 | 1554 | // alternative syntax using C#/.NET driver "In" method 1555 | var query = from e in collection.AsQueryable() 1556 | where e.Address.State.In(states) 1557 | select e; 1558 | ``` 1559 | 1560 | 1561 | ####$in/$all with arrays 1562 | ``` 1563 | var desiredSkills = new [] { "Java", "C#" }; 1564 | var query = from e in collection.AsQueryable() 1565 | where e.Skills.ContainsAny(desiredSkills) 1566 | select e; 1567 | 1568 | // translates to: 1569 | { "Skills" : { $in : [ "Java", "C#" ] } } 1570 | 1571 | 1572 | var query = from e in collection.AsQueryable() 1573 | where e.Skills.ContainsAll(desiredSkills) 1574 | select e; 1575 | 1576 | // translates to: 1577 | { "Skills" : { $all : [ "Java", "C#" ] } } 1578 | // note: ContainsAny and ContainsAll are defined by the C#/.NET 1579 | driver and are not part of standard LINQ 1580 | ``` 1581 | 1582 | 1583 | ####$elemMatch 1584 | ``` 1585 | var query = from e in collection.AsQueryable() 1586 | where 1587 | e.Addresses.Any(a => 1588 | a.City == "Hoboken" && 1589 | a.State == "NJ") 1590 | select e; 1591 | 1592 | // translates to: 1593 | { "Addresses" : { $elemMatch : 1594 | { City : "Hoboken", State : "NJ" } } } 1595 | ``` 1596 | 1597 | 1598 | ####Mixing LINQ with MongoDB queries 1599 | ``` 1600 | var query = from e in collection.AsQueryable() 1601 | where 1602 | e.Salary > 50000 && 1603 | Query.NotExists("EmployeeStatus").Inject() 1604 | select e; 1605 | 1606 | // translates to: 1607 | { 1608 | Salary : { $gt : 50000 }, 1609 | EmployeeStatus : { $exists : false } 1610 | } 1611 | ``` 1612 | 1613 | 1614 | 1615 | ###참고 문서 1616 | - What's new in the .NET Driver 1617 | http://www.slideshare.net/mongodb/webinar-whats-new-in-the-net-driver 1618 | - CSharp Driver LINQ Tutorial 1619 | http://docs.mongodb.org/ecosystem/tutorial/use-linq-queries-with-csharp-driver/ 1620 | 1621 | 1622 | 1623 | ###Error Code 1624 | http://www.mongodb.org/about/contributors/error-codes/ 1625 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CookBookMongoDB-CSharp 2 | C#으로 MongoDB를 사용하는 방법을 설명한다 3 | 4 | 5 | ## MongoDB 공식 C# Driver 6 | - 1.x와 2.x 라이브러리가 거의 완전 다르다. 7 | - [2.0 드라이버 소개](https://www.mongodb.com/blog/post/introducing-20-net-driver) 8 | - [레퍼런스](http://mongodb.github.io/mongo-csharp-driver/2.0/reference/) 9 | - [온라인 도움 문서](http://api.mongodb.org/csharp/2.0/html/R_Project_CSharpDriverDocs.htm) 10 | - [Indexes.CreateOneAsync sample](http://qiita.com/SHUAI/items/f9479f2c1a09bbd7e36b) 11 | - [Find & FindAsync sample](http://qiita.com/SHUAI/items/ace6f6d3f08bb8dd79c5) 12 | 13 | 14 | 15 | ## 목차 16 | - [MongoDB를 Windows에 설치](windowsInstall.md) 17 | - [wiredTiger 설정](wiredTiger.md) 18 | - [검색](find.md) 19 | - [추가/갱신/삭제](insert_update_delete.md) 20 | - [팁](tips.md) 21 | 22 | 23 | ## MongoDB C# 드라이버 설치 24 | - https://www.nuget.org/packages/MongoDB.Driver 25 | - NuGet으로 설치한다. 26 | 27 | 28 | 29 | ## MongoDB collection 객체 생성 30 | - 이 글의 코드에서 공통적으로 사용되는 것으로 MongoDB 접속 및 특정 Colection 객체를 만든다. 31 | 32 | ``` 33 | string DBName; // 데이터베이스 이름 34 | 35 | public static IMongoCollection GetDBCollection(string collectionName) 36 | { 37 | var mongoClient = GetDBClient(DBConnectString); 38 | if (mongoClient == null) 39 | { 40 | return null; 41 | } 42 | 43 | var collection = mongoClient.GetDatabase(DBName).GetCollection(collectionName); 44 | return collection; 45 | } 46 | 47 | 48 | static IMongoClient GetDBClient(string connectString) 49 | { 50 | try 51 | { 52 | // connectString 53 | // mongodb://testID:123asd@192.168.0.1:27017/?maxPoolSize=200&safe=true 54 | // mongodb://192.168.0.1:27017 55 | MongoClient cli = new MongoClient(connectString); 56 | return cli; 57 | } 58 | catch (Exception ex) 59 | { 60 | return null; 61 | } 62 | } 63 | ``` 64 | 65 | ## 데이터 정의 66 | - 객체 맵핑은 class만 가능하다 67 | ``` 68 | public class DBBasic 69 | { 70 | public string _id; // 유저ID 71 | public int Level; 72 | public int Exp; 73 | public Int64 Money; 74 | public List Costume; // 캐릭터 복장 아이템ID. 개수는 무조건 12 75 | } 76 | ``` 77 | ``` 78 | public class DBUserItem 79 | { 80 | public Int64 _id; // Unique ID 81 | 82 | public string UserID; 83 | 84 | public int ItemID; 85 | 86 | [MongoDB.Bson.Serialization.Attributes.BsonElement("AD")] 87 | public DateTime AcquireDateTime; // 아이템 입수 시간 88 | } 89 | ``` 90 | 91 | 92 |
93 |
94 |
95 | 96 | ### 볼 글 97 | - [MongoDB 3.2의 도큐먼트 검증 기능 설명](http://qiita.com/fetaro/items/97dd97046e0ba94dda40) 98 | - [(일어) query 예제 모음](http://qiita.com/nishina555/items/9e20211e8d6f12fdb7b7) 99 | - [(일어) query 예제 모음](http://qiita.com/Masaaki_Inaba/items/e35ccb58e6828ba84fc4) -------------------------------------------------------------------------------- /XamarinWorkbooks/mongoDB_delete.workbook: -------------------------------------------------------------------------------- 1 | --- 2 | uti: com.xamarin.workbook 3 | platforms: 4 | - Console 5 | packages: 6 | - id: MongoDB.Driver.Core 7 | version: 2.4.4 8 | - id: MongoDB.Driver 9 | version: 2.4.4 10 | - id: MongoDB.Bson 11 | version: 2.4.4 12 | - id: System.Runtime.InteropServices.RuntimeInformation 13 | version: 4.3.0 14 | --- 15 | 16 | ```csharp 17 | #r "MongoDB.Driver" 18 | ``` 19 | 20 | ```csharp 21 | using MongoDB.Driver; 22 | 23 | static IMongoCollection GetDBCollection(string dbIP, string dbName, string collectionName) 24 | { 25 | var database = GetMongoDatabase(dbIP, dbName); 26 | var collection = database.GetCollection(collectionName); 27 | return collection; 28 | } 29 | 30 | static IMongoDatabase GetMongoDatabase(string dbIP, string dbName) 31 | { 32 | MongoClient cli = new MongoClient(dbIP); 33 | return cli.GetDatabase(dbName); 34 | } 35 | ``` 36 | 37 | ```csharp 38 | var mongoDBIP = "mongodb://localhost:27017"; 39 | var mongoDBDatabaseName = "TestDB"; 40 | var mongoDBCollectionName = "GameUser1"; 41 | var Datas = GetDBCollection(mongoDBIP, mongoDBDatabaseName, mongoDBCollectionName); 42 | await Datas.DeleteManyAsync(new MongoDB.Bson.BsonDocument()); 43 | ``` -------------------------------------------------------------------------------- /find.md: -------------------------------------------------------------------------------- 1 | 2 | ### 모든 도큐먼트 가져오기 3 | - 클래스 맵핑 4 | ``` 5 | var collection = GetDBCollection("Basic"); 6 | var documents = await collection.Find(_ => true).ToListAsync(); 7 | return documents; 8 | ``` 9 | 10 | - BsonDocument 11 | ``` 12 | var collection = GetDBCollection("Basic"); 13 | var documents = await collection.Find(new BsonDocument()).ToListAsync(); 14 | return documents; 15 | ``` 16 | 17 | 18 | ### 검색 시 첫 번째 도큐먼트만 가져온다 19 | - 클래스 맵핑 사용 20 | 21 | ``` 22 | var collection = GetDBCollection("Basic"); 23 | 24 | // 기본으로는 Find 라는 메소드는 없다. Find는 확장 메소드로 사용하고 싶다면 25 | //using MongoDB.Driver.Core.Misc; 26 | //using MongoDB.Driver; 27 | //을 선언해야 한다. 28 | 29 | // 첫 번째 값 또는 없으면 null을 반환한다. 30 | var document = await collection.Find(x => x._id == userID).FirstOrDefaultAsync(); 31 | ``` 32 | 33 | 34 | ### 조건에 맞는 모든 도큐먼트를 가져온다 35 | ``` 36 | var collection = GetDBCollection("Basic"); 37 | var documents = await collection.Find(x=> x.Level >= level).ToListAsync(); 38 | return documents; 39 | ``` 40 | 41 | 42 | ### BsonDocument를 사용하여 검색 43 | - 도큐먼트의 필드를 수동으로 지정해야 한다. 44 | 45 | ``` 46 | var collection = GetDBCollection("Basic"); 47 | 48 | // useID와 동일한 도큐먼트들 검색. 49 | var filter = new BsonDocument("_id", userID); 50 | var documents = await collection.Find(filter).ToListAsync(); 51 | 52 | if (documents.Count > 0) 53 | { 54 | return documents[0]["Level"].AsInt32; // 도큐먼트에 저장된 타입과 다르면 예외 발생 55 | } 56 | 57 | return 0; 58 | ``` 59 | ``` 60 | var collection = GetDBCollection("Basic"); 61 | // Level이 2 이상인 도큐먼트를 검색 62 | var filter = new BsonDocument("Level", new BsonDocument("$gte", 2)); 63 | var documents = await collection.Find(filter).ToListAsync(); 64 | return documents; 65 | ``` 66 | 67 | - 복수의 조건으로 검색한다 68 | 69 | ``` 70 | // Builders를 사용할 때는 Collection은 BsonDocument를 사용해야 한다. 71 | 72 | var collection = GetDBCollection("Basic"); 73 | 74 | var builder = Builders.Filter; 75 | var filter = builder.Gte("Level", 2) & builder.Eq("Money", 1000); 76 | var documents = await collection.Find(filter).ToListAsync(); 77 | 78 | var IDList = new List(); 79 | 80 | foreach (var document in documents) 81 | { 82 | IDList.Add(document["_id"].AsString); 83 | } 84 | return IDList; 85 | ``` 86 | 87 | 88 | 89 | ### 특정 필드의 데이터만 가져오기 90 | - 도큐먼트의 모든 필드의 데이터가 아닌 일부 필드의 값만 가져온다. 91 | 92 | ``` 93 | var collection = GetDBCollection("Basic"); 94 | 95 | // Level만 96 | var documents = await collection.Find(new BsonDocument()).Project(BsonDocument.Parse("{Level:1}")).ToListAsync(); 97 | 98 | // Level, Money만 99 | //var documents = await collection.Find(new BsonDocument()).Project(BsonDocument.Parse("{Level:1, Money:1}")).ToListAsync(); 100 | ``` 101 | 102 | ``` 103 | var collection = GetDBCollection("Basic"); 104 | var projection = Builders.Projection.Include("Exp").Include("Level"); 105 | var documents = await collection.Find(x => true).Project(projection).ToListAsync(); 106 | ``` 107 | 108 | 109 | ### 도큐먼트의 특정 필드를 제외한 데이터만 가져오기 110 | 111 | ``` 112 | var collection = GetDBCollection("Basic"); 113 | 114 | // Level만 제외한다 115 | var documents = await collection.Find(new BsonDocument()).Project(BsonDocument.Parse("{Level:0}")).ToListAsync(); 116 | ``` 117 | 118 | 119 | ### Expression. 지정된 필드만, 필드를 다른 이름으로 120 | 121 | ``` 122 | var collection = GetDBCollection("Basic"); 123 | var projection = Builders.Projection.Expression(x => new { X = x.Level, Y = x.Exp }); 124 | var documents = await collection.Find(x => true).Project(projection).ToListAsync(); 125 | 126 | //var projection = Builders.Projection.Expression(x => new { X = x.X, Y = x.Y }); 127 | //var projection = Builders.Projection.Expression(x => new { Sum = x.X + x.Y }); 128 | //var projection = Builders.Projection.Expression(x => new { Avg = (x.X + x.Y) / 2 }); 129 | //var projection = Builders.Projection.Expression(x => (x.X + x.Y) / 2); 130 | ``` 131 | ``` 132 | // sort + projection + skip + limt 133 | //var userID = "jacking"; 134 | //int userLevel = 0; 135 | 136 | var projection = BsonDocument.Parse("{Level:1, Momey:1, Exp:1}"); 137 | var sort = BsonDocument.Parse("{Level:1}"); 138 | var options = new FindOptions 139 | { 140 | AllowPartialResults = true, 141 | BatchSize = 20, 142 | Comment = "funny", 143 | //CursorType = CursorType.TailableAwait, 144 | MaxTime = TimeSpan.FromSeconds(3), 145 | NoCursorTimeout = true 146 | }; 147 | 148 | var collection = GetDBCollection("Basic"); 149 | var documents = collection.Find(x => x.Exp >= 0, options).Project(projection) 150 | .Sort(sort) 151 | .Limit(30) 152 | .Skip(0).ToListAsync(); 153 | 154 | ``` 155 | 156 | 157 | ### Builders 사용 158 | 159 | ``` 160 | var collection = GetDBCollection("Basic"); 161 | 162 | var builder = Builders.Filter; 163 | var filter = builder.Eq(x => x._id, "jacking") & builder.Lt(x => x.Money, 1100); 164 | // or 165 | //var filter = builder.Eq("X", 10) & builder.Lt("Y", 20); 166 | // or 167 | //var filter = builder.Eq("x", 10) & builder.Lt("y", 20); 168 | // or 169 | //var filter = Builders.Filter.Where(x => x._id == "jacking" && x.Money < 1100); 170 | 171 | // 첫 번째 값 또는 null 172 | var document = await collection.Find(filter).FirstOrDefaultAsync(); 173 | ``` 174 | 175 | 176 | ### 배열 요소 조건 검색 177 | - 도큐먼트의 필드 중 배열이 있으 때 배열 요소 조건 검사. 178 | - 179 | ``` 180 | var collection = GetDBCollection("Basic"); 181 | 182 | // Costume 리스트의 요소 중 0 보다 크거나 같은 것이 있는 도큐먼트 검색 183 | var filter = Builders.Filter.AnyGt(x => x.Costume, 0); 184 | var documents = await collection.Find(filter).ToListAsync(); 185 | 186 | // 비동기로 검색 후 데이터를 비동기로 바로 사용 187 | var filter = new BsonDocument("x", new BsonDocument("$gte", 100)); 188 | await collection.Find(filter).ForEachAsync(async document => 189 | { 190 | await ProcessDocumentAsync(document); 191 | }); 192 | ``` 193 | 194 | 195 | ### 데이터 정의 196 | - 객체 맵핑은 class만 가능하다 197 | ``` 198 | public class DBBasic 199 | { 200 | public string _id; // 유저ID 201 | public int Level; 202 | public int Exp; 203 | public Int64 Money; 204 | public List Costume; // 캐릭터 복장 아이템ID. 개수는 무조건 12 205 | } 206 | ``` 207 | -------------------------------------------------------------------------------- /insert_update_delete.md: -------------------------------------------------------------------------------- 1 | 2 | ### 기본 추가 3 | - 클래스 맵핑으로 새 도큐먼트 추가 4 | 5 | ``` 6 | var newData = new DBBasic() 7 | { 8 | _id = "test01", 9 | Level = 1, 10 | Exp = 0, 11 | Money = 1000, 12 | Costume = new List(Enumerable.Repeat(0, 12)), 13 | }; 14 | 15 | // Basic 컬렉션에 추가한다 16 | var collection = Common.GetDBCollection("Basic"); 17 | await collection.InsertOneAsync(newData); 18 | ``` 19 | 20 | - BsonDocument를 사용하여 추가. 21 | 22 | ``` 23 | Int64 money = 1000; 24 | var Costume = new List(Enumerable.Repeat(0,12)); 25 | var document = new BsonDocument { { "_id", userID }, { "Level", 1 }, { "Exp", 0 }, { "Money", money }, { "Costume", new BsonArray(Costume) } }; 26 | 27 | var collection = GetDBCollection("Basic"); 28 | await collection.InsertOneAsync(document); 29 | ``` 30 | 31 | 32 | ### 한번에 복수의 document 추가 33 | - 한번의 요청으로 복수의 document를 추가한다. 34 | 35 | ``` 36 | var newItemList = new List(); 37 | 38 | foreach (var itemID in ItemIDList) 39 | { 40 | var newData = new DBUserItem() 41 | { 42 | _id = UniqueSeqNumberGenerator(), 43 | UserID = userID, 44 | ItemID = itemID, 45 | AcquireDateTime = DateTime.Now, 46 | }; 47 | 48 | newItemList.Add(newData); 49 | } 50 | 51 | var collection = GetDBCollection("Item"); 52 | await collection.InsertManyAsync(newItemList); 53 | ``` 54 | 55 | 56 | ### 정렬 57 | 58 | ``` 59 | var collection = GetDBCollection("Basic"); 60 | 61 | // 내림차순 62 | //var documents = await collection.Find(x=> x.Level >= 1).SortByDescending(d => d.Level).FirstOrDefaultAsync(); 63 | // or 64 | //var documents = await collection.Find(x=> x.Level >= 1).SortByDescending(d => d.Level).FirstOrDefaultAsync(); 65 | // or 66 | //var documents = await collection.Find(x=> x.Level >= 1).SortByDescending(d => d.Level).ToListAsync(); 67 | // or 조건 없이 68 | var documents = await collection.Find(x => true).SortByDescending(d => d.Level).ToListAsync(); 69 | ``` 70 | 71 | ``` 72 | var collection = GetDBCollection("Basic"); 73 | 74 | // 올림 차순 75 | //var documents = await collection.Find(new BsonDocument()).Sort(new BsonDocument("$Level", 1)).ToListAsync(); 76 | 77 | // 내림 차순 78 | //var documents = await collection.Find(new BsonDocument()).Sort(new BsonDocument("Level", -1)).ToListAsync(); 79 | // or 80 | var documents = await collection.Find(new BsonDocument()).Sort("{Level: -1}").ToListAsync(); 81 | ``` 82 | 83 | ``` 84 | // 복수의 조건으로 정렬 85 | var sort = Builders.Sort.Ascending("borough").Ascending("address.zipcode"); 86 | var result = await collection.Find(filter).Sort(sort).ToListAsync(); 87 | ``` 88 | 89 | 90 | ### FindOneAndReplaceAsync 91 | - 한번에 검색&교체 92 | 93 | ``` 94 | var collection = GetDBCollection("Basic"); 95 | 96 | var newData = new DBBasic() 97 | { 98 | _id = "jacking3", 99 | Money = 3333, 100 | Costume = new List(Enumerable.Repeat(0, 12)) 101 | }; 102 | 103 | // 변경 되기 이전 값을 반환한다. 실패하면 null 104 | var documents = await collection.FindOneAndReplaceAsync(x => x._id == "jacking5", newData); 105 | ``` 106 | 107 | ``` 108 | var collection = GetDBCollection("Basic"); 109 | 110 | var filter = new BsonDocument("_id", "jacking3"); 111 | 112 | // _id와 Level 필드만 도큐먼트에 남게된다. 113 | var replacement = BsonDocument.Parse("{Level: 12}"); 114 | //var projection = BsonDocument.Parse("{x: 1}"); 115 | //var sort = BsonDocument.Parse("{a: -1}"); 116 | var options = new FindOneAndReplaceOptions() 117 | { 118 | IsUpsert = false, // 이것을 true로 하면 도큐먼트가 없으면 추가한다. 119 | //Projection = projection, 120 | //ReturnDocument = returnDocument, 121 | //Sort = sort, 122 | MaxTime = TimeSpan.FromSeconds(2) 123 | }; 124 | 125 | var documents = await collection.FindOneAndReplaceAsync(filter, replacement, options, CancellationToken.None); 126 | ``` 127 | 128 | 129 | ### FindOneAndUpdateAsync 130 | - 한번에 검색&수정 131 | ``` 132 | var collection = GetDBCollection("Basic"); 133 | 134 | var filter = new BsonDocument("_id", "jacking3"); 135 | var update = BsonDocument.Parse("{$set: {Level: 3}}"); 136 | //var projection = BsonDocument.Parse("{x: 1}"); 137 | //var sort = BsonDocument.Parse("{a: -1}"); 138 | var options = new FindOneAndUpdateOptions() 139 | { 140 | //IsUpsert = isUpsert, 141 | //Projection = projection, 142 | //ReturnDocument = returnDocument, 143 | //Sort = sort, 144 | MaxTime = TimeSpan.FromSeconds(2) 145 | }; 146 | 147 | var document = await collection.FindOneAndUpdateAsync(filter, update, options, CancellationToken.None); 148 | ``` 149 | 150 | - BsonDocume 사용 151 | ``` 152 | var findUserName = textBox5.Text; 153 | var newNickNameList = new List() { textBox1.Text, textBox6.Text }; 154 | 155 | var collection = MongoDBLib.Common.GetDBCollection("GameUser2"); 156 | 157 | var filter = new BsonDocument("_id", findUserName); 158 | var update = Builders.Update.Set("NickNameList", new BsonArray(newNickNameList)); 159 | var options = new FindOneAndUpdateOptions 160 | { 161 | ReturnDocument = ReturnDocument.After 162 | }; 163 | 164 | var document = await collection.FindOneAndUpdateAsync(filter, update, options); 165 | 166 | if (document == null) 167 | { 168 | DevLog.Write(string.Format("GameUser2:{0} 닉네임 변경 실패", findUserName)); 169 | } 170 | else 171 | { 172 | var nickList = document["NickNameList"].AsBsonArray.Select(p => p.AsString).ToList(); 173 | 174 | DevLog.Write(string.Format("GameUser2:{0} 닉네임 변경 {1}, {2}", findUserName, nickList[0], nickList[1])); 175 | } 176 | ``` 177 | 178 | - 클래스 맵핑 사용 179 | ``` 180 | var findUserName = textBox5.Text; 181 | var newNickNameList = new List() { textBox1.Text, textBox6.Text }; 182 | 183 | var collection = MongoDBLib.Common.GetDBCollection("GameUser2"); 184 | 185 | var result = await collection.FindOneAndUpdateAsync( 186 | u => u._id == findUserName, 187 | Builders.Update.Set("NickNameList", new BsonArray(newNickNameList)), 188 | new FindOneAndUpdateOptions 189 | { 190 | ReturnDocument = ReturnDocument.After 191 | }); 192 | 193 | if (result == null) 194 | { 195 | DevLog.Write(string.Format("GameUser2:{0} 닉네임 변경 실패", findUserName)); 196 | } 197 | else 198 | { 199 | DevLog.Write(string.Format("GameUser2:{0} 닉네임 변경 {1}, {2}", findUserName, result.NickNameList[0], result.NickNameList[1])); 200 | } 201 | ``` 202 | 203 | 204 | ### 동적 기능 사용하기 205 | - C#의 다이나믹 타입 사용 206 | 207 | ``` 208 | dynamic person = new System.Dynamic.ExpandoObject(); 209 | person.FirstName = "Jane"; 210 | person.Age = 12; 211 | person.PetNames = new List { "Sherlock", "Watson" }; 212 | 213 | var collection = GetDBCollection("Persion"); 214 | await collection.InsertOneAsync(person); 215 | ``` 216 | 217 | 218 | ### UTC 시간 보정해서 데이터 넣기 219 | - MongoDB에 time 타입 데이터는 utc 기준으로 들어간다. 그래서 mongodb에서 보이는데 시간을 한국 시간과 같게 하려면 도큐먼트를 넣을 때 시간을 +9 한다. 220 | 221 | ``` 222 | var newData = new DBTimeData() 223 | { 224 | CurTime = DateTime.Now.AddHours(9) 225 | }; 226 | 227 | var collection = GetDBCollection("TimeData"); 228 | await collection.InsertOneAsync(newData); 229 | ``` 230 | 231 | 232 | ### Update 233 | #### 기본 업데이트 234 | 235 | ``` 236 | // UpdateOneAsync 는 하나만, 복수는 UpdateManyAsync 237 | var collection = GetDBCollection("Skill"); 238 | 239 | var userID = "jacking"; 240 | 241 | var result = await collection.UpdateOneAsync(x => x._id == userID, 242 | Builders.Update.Set(x => x.Value, 14)); 243 | // result.MatchedCount 가 1 보다 작으면 업데이트 한 것이 없음 244 | ``` 245 | 246 | #### 도큐먼트의 내부 도큐먼트를 변경할 때 247 | 248 | ``` 249 | var collection = GetDBCollection("Skill"); 250 | 251 | var userID = "jacking"; 252 | int skillItemID = 1; 253 | var newInfo = new SkillItemInfo() { Value = 101 }; 254 | 255 | 256 | var filter = Builders.Filter.And(Builders.Filter.Eq(x => x._id, userID), 257 | Builders.Filter.ElemMatch(x => x.SkillItems, x => x.ID == skillItemID)); 258 | 259 | var update = Builders.Update.Set("SkillItems.$.Info", newInfo); 260 | //or 261 | //var update = Builders.Update.Set(x => x.SkillItems.ElementAt(-1).Info, newInfo); 262 | 263 | collection.UpdateOneAsync(filter, update); 264 | ``` 265 | 266 | 267 | ### Replace 268 | 269 | ``` 270 | var collection = GetDBCollection("Basic"); 271 | 272 | var userID = "jacking"; 273 | var documents = await collection.Find(x=> x._id == userID).SingleAsync(); 274 | 275 | if( documents != null) 276 | { 277 | documents.Level = documents.Level + 3; 278 | var result = await collection.ReplaceOneAsync(x => x._id == documents._id, documents); 279 | ``` 280 | 281 | ``` 282 | var tom = await collection.Find(x => x.Id == ObjectId.Parse("550c4aa98e59471bddf68eef")) 283 | .SingleAsync(); 284 | 285 | tom.Name = "Thomas"; 286 | tom.Age = 43; 287 | tom.Profession = "Hacker"; 288 | 289 | var result = await collection.ReplaceOneAsync(x => x.Id == tom.Id, tom); 290 | ``` 291 | 292 | 293 | 294 | ### Delete 295 | #### 삭제. 한번에 복수개를 지울 때는 DeleteManyAsync 296 | ``` 297 | var collection = GetDBCollection("Basic"); 298 | 299 | var userID = "jacking4"; 300 | var result = await collection.DeleteOneAsync(x=> x._id == userID); 301 | ``` 302 | 303 | #### 컬렉션의 모든 문서 삭제 304 | ``` 305 | var collection = GetDBCollection("Basic"); 306 | await collection.DeleteManyAsync(new MongoDB.Bson.BsonDocument()); 307 | ``` 308 | -------------------------------------------------------------------------------- /tips.md: -------------------------------------------------------------------------------- 1 | ### MongoDB의 _id에서 시간을 추출하기 2 | MongoDB의 _id 값은(데이터를 넣을 때 MongoDB가 넣어주는 값의 상위 8 문자는 만들어질 때의 unixtime의 16진수 표현이다. 3 | 그래서 _id 값의 상위 8 문자를 추출해서 datetime으로 변환하면 시간을 알 수 있다. 4 | 5 | ``` 6 | string mongo_id = "57b3ce6269d7d0098ef3b603"; 7 | 8 | string hexString = mongo_id.Substring(0, 8); 9 | int num = Int32.Parse(hexString, System.Globalization.NumberStyles.HexNumber); 10 | 11 | Console.WriteLine(num); 12 | Console.WriteLine(DateTimeOffset.FromUnixTimeSeconds(num).ToLocalTime()); 13 | ``` 14 | -------------------------------------------------------------------------------- /windowsInstall.md: -------------------------------------------------------------------------------- 1 | ### MongoDB 3.0.6 Windows에서 설치 및 실행 2 | - [MongoDB 공식 다운로드](https://www.mongodb.org/downloads#production) 에서 'Windows 64-bit 2008 R2+'를 선택해서 다운로드 한다. 3 | - 기본 설치 위치는 C:\Program Files\MongoDB\Server\3.0\bin 4 | - 실행 파일을 Path에 추가한다. 5 | - cmd에서 mongod --version 가 실행되면 설치는 성공이다. 6 | - 데이터와 로그를 저장할 디렉토리를 만든다(이름은 마음대로 해도 괜찮다.) 7 | - 예)데이터. D:\mongodb\data 8 | - 예)로그. D:\mongodb\logs 9 | - 실행 10 | - cmd에서 'Mongod --dbpath D:\mongodb\data --logpath D:\mongodb\logs\mongodb.log' 11 | 12 | 13 | ### 서비스에 등록하기 14 | - 관리자 권한으로 --install 옵션을 붙여서 MongoDB를 실행한다. 15 | - mongod --remove로 서비스에서 제거할 수 있다. 16 | 17 | 18 | ### 설정파일 사용 19 | - 매번 실행할 때마다 설정 옵션을 입력하기 귀찮으면 설정 파일을 사용한다. 20 | - .conf 파일을 만든다. 21 | - 관리자권한으로 'mongod --install --config D:\mongodb\mongodb.conf' 22 | - conf 파일은 utf-8 로 한다. 23 | - 설정 예 24 | 25 | ``` 26 | storage: 27 | dbPath: D:\mongodb\data 28 | engine: wiredTiger 29 | journal: 30 | enabled: true 31 | 32 | systemLog: 33 | destination: file 34 | path: D:\mongodb\logs\mongodb.log 35 | 36 | net: 37 | bindIp: 127.0.0.1 38 | 39 | processManagement: 40 | windowsService: 41 | serviceName: MongoDB 42 | displayName: MongoDB 43 | description: MongoDB 서비스 44 | # serviceUser: 45 | # servicePassword: 46 | ``` 47 | 48 | 49 | ### 참고 50 | - 이 글은 [이것](http://qiita.com/moto_pipedo/items/c3bb40370ba2792143ad)을 정리한 것이다. 51 | -------------------------------------------------------------------------------- /wiredTiger.md: -------------------------------------------------------------------------------- 1 | 2 | ### wiredTiger 사용 conf 파일 예 3 | 4 | ``` 5 | // mongodb_wt.conf 6 | storage: 7 | dbPath: "/data/mongod_wt" 8 | engine: "wiredTiger" 9 | directoryPerDB: true 10 | wiredTiger: 11 | engineConfig: 12 | cacheSizeGB: 1 13 | directoryForIndexes: true 14 | statisticsLogDelaySecs: 0 15 | collectionConfig: 16 | blockCompressor: "snappy" 17 | indexConfig: 18 | prefixCompression: true 19 | journal: 20 | enabled: true 21 | systemLog: 22 | destination: file 23 | path: "/var/log/mongodb/mongodb_wt.log" 24 | logAppend: true 25 | processManagement: 26 | fork: true 27 | ``` 28 | 29 | 30 | ### storage설정 항목 사례 31 | - dbpath 32 | - 데이터베이스 파일 생성 디렉토리 33 | - journal 34 | - 저널 파일 작성 여부 35 | - directoryPerDB 36 | - 기본 false. 데이터베이스 마다 디렉토리를 생성 할지 37 | - engine 38 | - 스토리지 엔진의 선택 39 | - mmapv1: 기존 스토리지 엔진 40 | - wiredTiger: wiredTiger 스토리지 엔진 41 | - 3.0 이라면 wiredTiger를 사용하는 것이 좋다 42 | 43 | 44 | 45 | ### wiredTiger 설정 항목 사례 46 | #### engineConfig 47 | - cacheSizeGB 48 | - 기본적으로 시스템 메모리의 절반 or 1GB. 49 | - wiredTiger에서 실제 데이터를 캐시 하기 위한 메모리 영역 지정. 50 | - 쓰레드와 Index도 메모리를 먹으므로 처음에는 시스템 메모리의 6~7할 정도가 좋다고 생각한다 51 | - directoryForIndexes 52 | - MySQL의 innodb_file_per_table과 비슷 53 | - statisticsLogDelaySecs 54 | - 기본 값은 0(출력하지 않는다) 55 | - wiredTiger 통계 정보 파일을 몇 초 만에 출력하까를 설정. 56 | - 0 으로 하면 출력하지 않는다. 57 | - 출력 시에 부하가 생기는 경향이 있으므로 테스트 시는 30초 정도로 설정하고 실 서비스 때는 10분에 한번이나 안 나오게 설정하는 것이 좋다. 58 | 59 | ####collectionConfig 60 | - blockCompressor 61 | - 데이터 압축 여부. 기본 값은 snappy. 압축 시의 CPU 부하 등이 신경이 쓰이면 none 으로 62 | - none: 압축하지 않는다 63 | - snappy: 적당한 압축률로 고속으로 압축 64 | - zlib: snappy 보다 압축률은 좋지만 저속 65 | 66 | 67 | #### indexConfig 68 | - prefixCompression 69 | - 기본 True. index 압축 여부 70 | 71 | 72 | 73 | ### wiredTiger 캐시 사이즈 확인 74 | - 현재 설정 확인 75 | ``` 76 | db.serverStatus().wiredTiger 77 | ``` 78 | 79 | - 캐시 설정 80 | ``` 81 | db.serverStatus().wiredTiger.cache["maximum bytes configured"] 82 | ``` 83 | 84 | 85 | ### 참고 86 | - http://qiita.com/kuwa_tw/items/0a5704e9e505cffeae34 87 | - http://qiita.com/takiuchi/items/309bfa7475d1c4666389 88 | --------------------------------------------------------------------------------