2017-08-01 147 views
0

我有一个类似于以下用于存储许可证的文档。不必要的字段被删除。在MongoDB中使用C#驱动程序2.4.4更新两次嵌套文档3.4.6

{ 
    "_id" : "1", 
    "company_name" : "stackOverflow", 
    "license_holders" : [ 
    { 
     "UID" : "AAA-BBB-CCC-DDD", 
     "software_version" : "1.2.3", 
     "licenses" : [ 
     { 
      "creation_date" : "03.03.17", 
      "is_valid" : true, 
      "license_id" : "l1" 
     }, 
     { 
      "creation_date" : "03.03.16", 
      "is_valid" : false, 
      "license_id" : "l2" 
     } 
     ] 
    }, 
    { 
     "UID" : "111-222-333-444", 
     "software_version" : "1.2.3", 
     "licenses" : [ 
     { 
      "creation_date" : "05.05.17", 
      "is_valid" : true, 
      "license_id" : "l3" 
     }, 
     { 
      "creation_date" : "05.05.16", 
      "is_valid" : false, 
      "license_id" : "l4" 
     } 
     ] 
    } 
    ] 
} 

我可以通过这个查询更新的软件版本与给定UID:

public async Task<Customer> UpdateLicenseHolderSoftwareVersion(string uid, string softwareVersion) { 
     var update = Builders<Customer>.Update.Set(c => c.LicenseHolders[-1].CurrentSoftwareVersion, softwareVersion); 
     Customer customer = await DMSLicenseCollection.FindOneAndUpdateAsync(c => c.LicenseHolders.Any(h => h.UID == uid), update); 
     return customer; 
    } 

我无法找到一个方法来更新许可证的"is_valid"场。我正在尝试使用UIDLicenseId字段选择正确的许可证。我尝试了很多东西,但没有成功。嵌入这么多文档是不好的做法?或者我缺少一种方法来更新和检索数组内的几层嵌套文档。谢谢...

回答

0

我有几条建议可以让你的生活更轻松。

  • 我发现有用的是不将嵌套的文档存储为列表,但词典。这样你可以很容易地找到你想要更新的子文档。例如,UID和license_id可以是您的字典中的键,并且可以为字段的其余部分赋值。
  • 我不是一个非常喜欢在db中识别不是主键的东西。这里您根据UID和license_id更新子文档。我认为这是不好的做法,并建议你改变这一点。
  • 对于内嵌大量嵌套文档的大文档,您需要适度地了解您的行程。更多嵌套文档意味着更慢的查询执行。我建议你测试你的应用程序并检查你是否满意速度。

解决方案为您当前的问题:

public async Task ToggleLicesneIsValid(string UID, int licenseId) 
    { 
     var filter = Builders<Customer>.Filter.ElemMatch(x => x.licence_holders, i => i.UID == UID); 
     var customer = DMSLicenseCollection.Find(filter).FirstOrDefault(); 
     var item = customer.licence_holders.FirstOrDefault(x => x.UID == UID).licenses.FirstOrDefault(y => y.license_id == licenseId); 

     item.is_valid = !item.is_valid; 

     await DMSLicenseCollection.ReplaceOneAsync(o => o.mongoId == customer.mongoId, customer); 
    } 

此法切换真/假的“is_valid”但我建议你有2种独立的方法(用于设置一个设定是真的,一个是假的) 。这样代码更具可读性,您可以避免潜在的错误。

PS我在我的测试中将id命名为mongoId,但将其更改为您的喜好。

干杯!

+0

感谢您的建议,特别是对于字典之一。根据mongoDB,UID和license_id字段保证是唯一的,但它们不是主键。我发现你的解决方案替代了整个文档,而不是试图自动更新字段。我试图找到一种方法,只在可能的情况下替换许可证文件,而不是整个客户文件。感谢你的回答 :) – qua11q7

相关问题