MongoDB构建Filter时出现Unsupported filter: Contains(value(System.String[]))异常
异常产生原因
MongoDB C# 驱动构建过滤器时,会将 Lambda 表达式翻译为 MongoDB 服务端可执行的原生查询语句。你代码中用到的EncryptHelper.DecryptText是自定义C#方法,MongoDB 服务端不存在对应的实现,驱动无法将该方法调用转换为合法的MongoDB查询语法,因此抛出不支持的过滤器异常。
你没有调用自定义方法的过滤器可以正常运行,是因为单纯的字段包含判断可以直接被翻译为MongoDB原生的$in操作符。
解决方案
有两种可落地的解决思路,优先选择第一种:
方案1(推荐):提前加密过滤条件,查询时直接匹配加密字段
你不需要在查询时解密数据库存储的字段,而是反过来将待匹配的明文列表提前加密,直接用加密后的列表匹配数据库中已加密的CreatedBy字段,整个查询可完全推送到MongoDB服务端执行,性能最优。
代码示例:
// 先实现和DecryptText逻辑对称的加密方法,将过滤列表的所有明文转为加密值 var encryptedFilterList = filterJsonObj.HeaderFilterCreatedByList .Select(plainValue => EncryptHelper.EncryptText(plainValue)) .ToList(); // 构建过滤器,直接匹配加密字段,可正常翻译为$in查询 var filter = Builders<Documents>.Filter.Where(x => encryptedFilterList.Contains(x.CreatedBy));
如果你的CreatedBy字段存储的是多个加密值用逗号拼接的字符串,可调整为使用MongoDB的正则匹配过滤器,或者优化存储结构将多值改为数组类型存储,更便于查询。
方案2(仅适合小数据量场景):内存中做解密过滤
如果你的业务场景无法提前加密过滤条件,且当前查询匹配的数据量极小,可以先将符合其他过滤条件的全部数据查询到内存中,再在内存侧执行解密和匹配逻辑。
代码示例:
// 先执行其他过滤条件,拉取数据到内存 var tempResult = collection.Find(其他过滤条件).ToList(); // 内存中执行解密和包含判断 var finalResult = tempResult.Where(x => filterJsonObj.HeaderFilterCreatedByList.Contains(EncryptHelper.DecryptText(x.CreatedBy))).ToList();
注意该方案在数据量较大时会有严重的性能问题,不建议在生产环境核心业务中使用。
内容的提问来源于stack exchange,提问作者Manoj Naik
相关产品推荐
相关产品推荐

