如何用C#驱动在无类MongoDB中匹配前缀handler文档?
解决MongoDB C#无类架构下前缀匹配查询问题
你遇到的问题在于,你的LINQ表达式inputstring.StartsWith(x["handler"].AsString)无法被MongoDB C#驱动转换成服务器端查询——驱动会把所有文档拉到本地后再过滤,不仅效率极低,还可能因为驱动无法解析这个客户端方法调用而导致无结果或异常。
我们需要构造一个服务器端执行的查询,直接在MongoDB中判断输入字符串是否以handler字段的值为前缀,以下是具体解决方案:
正确的C#代码实现
String inputstring = "westtown"; IMongoCollection<BsonDocument> collection = null; List<BsonDocument> pages = null; try { collection = db.GetCollection<BsonDocument>("handlers"); // 构造服务器端查询:判断输入字符串的前N个字符(N为handler字段长度)是否等于handler值 var query = new BsonDocument("$expr", new BsonDocument("$eq", new BsonArray { "$handler", new BsonDocument("$substrCP", new BsonArray { inputstring, 0, new BsonDocument("$strLenCP", "$handler") }) })); pages = await collection.Find(query).ToListAsync(); } // 后续异常处理代码...
代码逻辑解释
$expr:允许在查询中使用聚合表达式,实现字段值与动态计算值的比较。$strLenCP:计算handler字段的字符长度(支持Unicode字符,避免多字节字符长度计算错误)。$substrCP:从输入字符串的起始位置(索引0)截取长度等于handler字段长度的子串。$eq:比较截取后的子串与handler字段值是否相等,相等则说明输入字符串以该handler值为前缀。
可选正则表达式方案(仅适合特定场景)
如果能预先确定handler字段的格式(比如都是短单词),也可以用正则表达式匹配输入字符串的所有可能前缀,但这种方式在输入字符串较长时会生成大量前缀,性能不如$expr方案:
// 生成输入字符串的所有前缀并构造正则表达式 var prefixRegex = new BsonRegularExpression($"^({string.Join("|", GetAllPrefixes(inputstring))})$"); var query = new BsonDocument("handler", prefixRegex); // 辅助方法:生成输入字符串的所有前缀 List<string> GetAllPrefixes(string input) { var prefixes = new List<string>(); for(int i=1; i<=input.Length; i++) { prefixes.Add(input.Substring(0, i)); } return prefixes; }
内容的提问来源于stack exchange,提问作者yosi madsu
相关产品推荐
相关产品推荐

