C#中SortedList存入MongoDB的键名含点号问题求助
解决方案
MongoDB不允许文档键名包含半角点号.(因为它被用来表示层级路径),针对你遇到的问题,以下是几种可行的解决办法:
1. 键名双向转义
把键名里的半角点号替换成MongoDB允许的合法字符(比如全角点号.),在存储和读取时统一做转换,确保前后一致:
// 存储:将半角点替换为全角点 var escapedKey = strName.Replace('.', '.'); var updateDefinition = Builders<User>.Update.Set($"lesPortefeuilles.sorPortefeuilles.{escapedKey}", value); // 读取:将全角点转回半角点 var filter = Builders<User>.Filter.Exists($"lesPortefeuilles.sorPortefeuilles.{escapedKey}"); var user = await collection.Find(filter).FirstOrDefaultAsync(); // 从文档中取出键时转回原键名 var originalKey = escapedKey.Replace('.', '.');
如果之前直接替换没成功,大概率是只处理了存储环节,没在读取时做反向转换,或者选了MongoDB不允许的替换字符(比如$),全角点号是安全且直观的选择。
2. 使用BsonDocument直接赋值
不要通过字符串拼接路径的方式调用Set,而是构造BsonDocument来传递带点号的键,让MongoDB将其识别为单个键名而非层级路径:
// 如果是新增或覆盖整个子文档 var subDoc = new BsonDocument(strName, BsonValue.Create(value)); var updateDefinition = Builders<User>.Update.Set("lesPortefeuilles.sorPortefeuilles", subDoc); // 如果是在已有子文档中添加新键(不覆盖原有内容) var updateDoc = new BsonDocument { { "$set", new BsonDocument { { $"lesPortefeuilles.sorPortefeuilles.{strName}", value } }} }; await collection.UpdateOneAsync(filter, updateDoc);
这种方式直接绕开了路径解析,确保带点号的键被正确存储为单个字段名。
3. 将SortedList转换为数组存储
如果你的SortedList键名经常包含特殊字符,建议放弃将其映射为MongoDB嵌套文档的方式,转而转换成键值对数组存储:
// 先定义一个用于存储键值对的类 public class PortefeuilleItem { public string Key { get; set; } public object Value { get; set; } // 根据实际数据类型调整 } // 存储:将SortedList转为键值对数组 var portefeuilleItems = sortedList.Select(kv => new PortefeuilleItem { Key = kv.Key, Value = kv.Value }).ToList(); var updateDefinition = Builders<User>.Update.Set("lesPortefeuilles.sorPortefeuilles", portefeuilleItems); // 查询:按Key字段过滤 var filter = Builders<User>.Filter.ElemMatch( "lesPortefeuilles.sorPortefeuilles", Builders<PortefeuilleItem>.Filter.Eq(p => p.Key, strName) );
这种方式从根源上避免了键名特殊字符的问题,适合键名不确定性较高的场景。
内容的提问来源于stack exchange,提问作者Philippe Lambert
相关产品推荐
相关产品推荐

