C# MongDb踩坑记录--分片写入报错 An upsert on a sharded collection must contain the shard key and have the simple collation.
环境
C# mongdb.driver collection分片 _id为片键
报错信息
A write operation resulted in an error. WriteError: { Category : "Uncategorized", Code : 61, Message : "An upsert on a sharded collection must contain the shard key and have the simple collation. Update request: { q: { MD5: "115C26E62D97F1F1866410A44B155A48" }, u: { $setOnInsert: { MD5: "115C26E62D97F1F1866410A44B155A48", BUSINESSETYPE: "融资", MEMBERSHORT: "中券", SECURITYCODE: "51rr00", ENDDATE: "20210128", MARGINBALANCE: "175370385", EITIME: new Date(1677813422216), SEGMENTID: "ECDP-01ef0e9bc539412da72b49041fa87e53", _id: ObjectId('640166ae745c52a624eec348'), EID: 17342 } }, multi: false, upsert: true }, shard key pattern: { _id: 1.0 }" }.
错误解析
- 没有包含分片键:每个分片集合都必须有一个分片键,用于标识数据在哪个分片中存储。在进行更新或插入操作时,需要确保将分片键作为查询条件一起传入。如果没有传入分片键,Mongodb就无法判断数据应该存储在哪个分片中,从而导致操作失败。
- 使用了不相容的排序规则:分片集合的排序规则必须是简单的,即只包含单个字段的升序或降序。如果排序规则不符合要求,也会导致upsert操作失败。
解决
- 确认是否正确传入了分片键:根据错误信息中的提示,首先需要确认在upsert操作中是否传入了分片键。可以检查传入的查询条件是否正确,是否包含了分片键字段。如果没有,需要修改代码,将分片键作为查询条件传入。
- 确认是否使用了正确的排序规则:如果确认已经正确传入了分片键,还需要检查集合的排序规则是否符合要求。可以通过检查数据库设置或集合定义来确认。如果排序规则不符合要求,需要修改集合的定义,使其符合要求。
基于我们当前的具体报错信息 我们已经包含了片键 _id 所以是缺少排序规则 在更新时 指定排序规则即可
var filter = Builders<BsonDocument>.Filter.Eq("MD5", "115C26E62D97F1F1866410A44B155A48");
var update = Builders<BsonDocument>.Update.SetOnInsert("MD5", "115C26E62D97F1F1866410A44B155A48")
.SetOnInsert("BUSINESSETYPE", "融资")
.SetOnInsert("MEMBERSHORT", "中券")
.SetOnInsert("SECURITYCODE", "51rr00")
.SetOnInsert("ENDDATE", "20210128")
.SetOnInsert("MARGINBALANCE", "175370385")
.SetOnInsert("EITIME", new DateTime(2023, 12, 31))
.SetOnInsert("SEGMENTID", "ECDP-01ef0e9bc539412da72b49041fa87e53")
.SetOnInsert("_id", ObjectId.GenerateNewId())
.SetOnInsert("EID", 17342);
var options = new UpdateOptions { IsUpsert = true, Collation = new Collation("zh", strength: CollationStrength.Primary) };
var result = await collection.UpdateOneAsync(filter, update, options);