我正在尝试创建一个简单的REST API,它能够使用一些简单的URL查询参数来过滤资源,例如:***"/Profile?firstName=Brian&age=26”***。我不需要任何高级过滤,只需找到所有匹配的内容即可。
我在.Net 6和MongoDB中使用最小API。驱动程序(2.17.1)
我有一个“解决方案”,工作,但它的错误倾向,是不是很可扩展或灵活。
如何能够读取查询参数,而不硬编码每个端点的特定名称和类型,同时不丢失参数的类型。如果可能,请使用过滤器生成器,而不是json。
当前“解决方案”:
配置文件类的一部分
public class Profile : Entity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
...
public List<BasePreference> Preferences { get; set; }
public Profile()
{
Preferences = new List<BasePreference>();
}
}
应用程序.MapGet(“/配置文件”,测试2);
private static async Task<IResult> Test2(
IRepository<Profile> repo,
string? firstName,
string? lastName,
int? age)
{
Dictionary<string, object?> queryDict= new Dictionary<string, object?>();
queryDict.Add(nameof(firstName),firstName);
queryDict.Add(nameof(lastName),lastName);
queryDict.Add(nameof(age), age);
foreach (var pair in queryDict)
{
if(pair.Value is null)
{
data.Remove(pair.Key);
}
}
var query = JsonSerializer.Serialize(data);
var content = await repo.ReadMany(query);
return Results.Ok(content);
}
MongoDB储存库片段
private IMongoCollection<T> collection;
public MongoDBRepository(IOptions<MongoDBSettings> mongoDBSettings)
{
MongoClient client = new MongoClient(mongoDBSettings.Value.ConnectionURI);
IMongoDatabase database = client.GetDatabase(mongoDBSettings.Value.DatabaseName);
collection = database.GetCollection<T>(typeof(T).Name.ToLower());
}
public async Task<List<T>> ReadMany(string query)
{
FilterDefinition<T> filter = query;
List<T> list = await collection.Find(filter).ToListAsync();
return list;
}
我对这种方法的问题是多方面的:
- 为多个资源重复实施此解决方案会让人头脑发昏,而且容易出错
- MongoDB内的大写字母必须完全匹配
- 对Model类的更改需要在项目的不同部分进行多次更改
- 它不能处理任何“复杂”的数据类型。例如,日期时间,GUID。
我尝试过的事情
我尝试过将所有内容转换为Json字符串并忽略类型,但是根据MongoDB,age:“25”=/= age:25。
- 然后,我搜索了在mongoDB中允许“25”== 25的方法,但没有任何运气。我尝试创建一个只包含可查询属性的ProfileQueryModel,然后使用[FromParameters],但无法使绑定工作,也不确定如何将其转换为FilterDefinition。
- 我试过将搜索查询Map到Dictionary〈string,object〉,但没有成功。我读到.Net 7可能包含了一种实现这一点的方法,但还没有发布。
- 我曾尝试将查询参数设置为单个json对象,例如“/profiles?query={“firstName”:“Brian”,“age”:25”},但再次将其作为字符串设置在int上
我在寻找什么
我不需要能够过滤数组或子对象中的元素。只要在所有给定的字段上进行简单的相等。理想情况下,我希望有一个解决方案,我不使用Json作为FilterDefinition,因为这看起来不太可能与更高级的数据类型中断,也不需要任何Json转换。但我已经为一个多星期了,我对我能得到的任何改进都很满意。
感谢提前和感谢阅读到目前为止。
1条答案
按热度按时间pinkon5k1#
您可以只迭代参数并为mongo构建过滤器字符串吗?
例如:
另请参阅:similar
**已添加:**我是这样做的,在this post的帮助下,通过循环
Request.Query
并使用FilterDefinitionBuilder
路线:
BuildFilter(查询字符串分析)
这不是仅用于&运算符,需要构建出OR(
builder.OR
)