在MongoDB中使用C#驱动程序2.4.4更新两次嵌套文档3.4.6
问题描述:
我有一个类似于以下用于存储许可证的文档。不必要的字段被删除。在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"
场。我正在尝试使用UID
和LicenseId
字段选择正确的许可证。我尝试了很多东西,但没有成功。嵌入这么多文档是不好的做法?或者我缺少一种方法来更新和检索数组内的几层嵌套文档。谢谢...
答
我有几条建议可以让你的生活更轻松。
- 我发现有用的是不将嵌套的文档存储为列表,但词典。这样你可以很容易地找到你想要更新的子文档。例如,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,但将其更改为您的喜好。
干杯!
感谢您的建议,特别是对于字典之一。根据mongoDB,UID和license_id字段保证是唯一的,但它们不是主键。我发现你的解决方案替代了整个文档,而不是试图自动更新字段。我试图找到一种方法,只在可能的情况下替换许可证文件,而不是整个客户文件。感谢你的回答 :) – qua11q7