.NET/C# API查询时忽略INT类型空值的实现方法
实现忽略空值INT参数的MongoDB查询过滤
我用.NET/C#开发API,现有一个查询MongoDB的服务函数,当前所有过滤条件强制要求传入非空值,但需要实现当INT类型过滤参数为null时忽略该条件(当作通配符使用)。
现有代码
服务查询函数
public async Task<List<Item>> GetAsync(RequestParameters requestParameters) => await _itemsCollection.Find(item => (item.item_description.Contains(requestParameters.FilterDescString) || item.item_adddesc.Contains(requestParameters.FilterDescString)) && item.item_id.Equals(requestParameters.FilterItemIdInt) && item.item_amount.Equals(requestParameters.FilterAmountInt) && item.item_width.Equals(requestParameters.FilterWidthInt) && item.item_height.Equals(requestParameters.FilterHeightInt) && item.item_weight.Equals(requestParameters.FilterWeightInt) && item.item_aunumber.Contains(requestParameters.FilterAunumberString)) .SortByDescending(i => i.item_id).Skip((requestParameters.PageNumber)* requestParameters.PageSize).Limit(requestParameters.PageSize) .ToListAsync();
RequestParameters模型
public class RequestParameters { const int MaxPageSize = 50; public int PageNumber { get; set; } = 1; private int _pageSize = 25; private string _filterDescString = ""; private string _filterAunumberString = ""; private int? _filterItemIdInt = null; private int? _filterAmountInt = null; private int? _filterWidthInt = null; private int? _filterHeightInt = null; private int? _filterWeightInt = null; public int PageSize { get { return _pageSize; } set { _pageSize = (value > MaxPageSize) ? MaxPageSize : value; } } public string FilterDescString { get { return _filterDescString; } set { _filterDescString = (value != null) ? value : _filterDescString; } } public string FilterAunumberString { get { return _filterAunumberString; } set { _filterAunumberString = (value != null) ? value : _filterAunumberString; } } public int? FilterItemIdInt { get { return _filterItemIdInt; } set { _filterItemIdInt = (value != null) ? value : _filterItemIdInt; } } public int? FilterAmountInt { get { return _filterAmountInt; } set { _filterAmountInt = (value != null) ? value : _filterAmountInt; } } public int? FilterWidthInt { get { return _filterWidthInt; } set { _filterWidthInt = (value != null) ? value : _filterWidthInt; } } public int? FilterHeightInt { get { return _filterHeightInt; } set { _filterHeightInt = (value != null) ? value : _filterHeightInt; } } public int? FilterWeightInt { get { return _filterWeightInt; } set { _filterWeightInt = (value != null) ? value : _filterWeightInt; } } }
当前问题
当调用接口时传入空值INT参数(比如初始调用):
https://localhost:7010/api/Items?PageNumber=0&PageSize=25&FilterDescString=&FilterAunumberString=&FilterAmountInt=null&FilterWidthInt=null&FilterHeightInt=null&FilterWeightInt=null&FilterItemIdInt=null
此时会返回空数组,因为原逻辑强制要求所有INT参数匹配null值,但数据库中没有对应字段为null的数据。
解决方案
方案1:直接修改查询表达式
针对每个可空INT参数,添加「参数为null则跳过该条件」的逻辑,修改后的查询函数如下:
public async Task<List<Item>> GetAsync(RequestParameters requestParameters) => await _itemsCollection.Find(item => // 字符串过滤逻辑保持不变 (item.item_description.Contains(requestParameters.FilterDescString) || item.item_adddesc.Contains(requestParameters.FilterDescString)) && // INT参数为空则忽略,否则匹配对应字段 (requestParameters.FilterItemIdInt == null || item.item_id.Equals(requestParameters.FilterItemIdInt)) && (requestParameters.FilterAmountInt == null || item.item_amount.Equals(requestParameters.FilterAmountInt)) && (requestParameters.FilterWidthInt == null || item.item_width.Equals(requestParameters.FilterWidthInt)) && (requestParameters.FilterHeightInt == null || item.item_height.Equals(requestParameters.FilterHeightInt)) && (requestParameters.FilterWeightInt == null || item.item_weight.Equals(requestParameters.FilterWeightInt)) && item.item_aunumber.Contains(requestParameters.FilterAunumberString) ) .SortByDescending(i => i.item_id) .Skip(requestParameters.PageNumber * requestParameters.PageSize) .Limit(requestParameters.PageSize) .ToListAsync();
逻辑说明
- 对于每个可空INT参数,判断逻辑改为:
参数为null 或者 字段值等于参数值 - 当参数为null时,表达式直接返回true,相当于跳过该过滤条件
- 当参数有值时,执行原本的字段匹配逻辑
方案2:使用FilterBuilder动态拼接条件(推荐)
如果后续过滤条件较多,推荐用MongoDB的FilterDefinitionBuilder动态拼接过滤条件,代码可读性和可维护性更强:
public async Task<List<Item>> GetAsync(RequestParameters requestParameters) { var filterBuilder = Builders<Item>.Filter; var filter = filterBuilder.Empty; // 添加字符串过滤条件 var descFilter = filterBuilder.Or( filterBuilder.Where(item => item.item_description.Contains(requestParameters.FilterDescString)), filterBuilder.Where(item => item.item_adddesc.Contains(requestParameters.FilterDescString)) ); filter &= descFilter; var aunumberFilter = filterBuilder.Where(item => item.item_aunumber.Contains(requestParameters.FilterAunumberString)); filter &= aunumberFilter; // 动态添加INT过滤条件 if (requestParameters.FilterItemIdInt.HasValue) { filter &= filterBuilder.Where(item => item.item_id.Equals(requestParameters.FilterItemIdInt.Value)); } if (requestParameters.FilterAmountInt.HasValue) { filter &= filterBuilder.Where(item => item.item_amount.Equals(requestParameters.FilterAmountInt.Value)); } if (requestParameters.FilterWidthInt.HasValue) { filter &= filterBuilder.Where(item => item.item_width.Equals(requestParameters.FilterWidthInt.Value)); } if (requestParameters.FilterHeightInt.HasValue) { filter &= filterBuilder.Where(item => item.item_height.Equals(requestParameters.FilterHeightInt.Value)); } if (requestParameters.FilterWeightInt.HasValue) { filter &= filterBuilder.Where(item => item.item_weight.Equals(requestParameters.FilterWeightInt.Value)); } return await _itemsCollection.Find(filter) .SortByDescending(i => i.item_id) .Skip(requestParameters.PageNumber * requestParameters.PageSize) .Limit(requestParameters.PageSize) .ToListAsync(); }
优势
- 逻辑拆分清晰,每个过滤条件单独处理
- 避免长表达式嵌套,可读性更强
- 方便后续扩展更多过滤条件
内容的提问来源于stack exchange,提问作者meDom
相关产品推荐
相关产品推荐

