I have a "Licenses" query which returns a Licenses[] object as follows:
var licenses = await _licenseRepository.SearchAsync(ct); //=> CT = CancellationToken
and a request filter which allows to filer by Id or Name:
public sealed record Filter(LicenseTypeValues[] Id, string[] Name);
So I should be able to pass a string[] as "Name" filter (for example) and I should return every License which name contains any of the names in the string[] -or part of them-.
Let's consider the following return from the licenses query with no filter:
{
"count": 5,
"results": [
{
"id": 15005,
"name": "Windows 2012",
"maxCpu": null,
"parentId": 15032,
"created": "2021-02-16T08:17:45Z"
},
{
"id": 15027,
"name": "Windows 2016",
"maxCpu": null,
"parentId": 15032,
"created": "2021-02-16T08:17:45Z"
},
{
"id": 15030,
"name": "Windows 2022",
"maxCpu": null,
"parentId": 15032,
"created": "2021-08-11T10:29:36Z"
},
{
"id": 15032,
"name": "Ubuntu 23",
"maxCpu": null,
"parentId": 15,
"created": "2023-05-22T14:56:11.93Z"
},
{
"id": 15032,
"name": "Ubuntu 24",
"maxCpu": null,
"parentId": 15,
"created": "2023-05-22T14:56:11.93Z"
}
]
}
Then, if I pass a filter like the following:
["Windows 201", "Ubuntu 23"]
the response should be:
{
"count": 3,
"results": [
{
"id": 15005,
"name": "Windows 2012",
"maxCpu": null,
"parentId": 15032,
"created": "2021-02-16T08:17:45Z"
},
{
"id": 15027,
"name": "Windows 2016",
"maxCpu": null,
"parentId": 15032,
"created": "2021-02-16T08:17:45Z"
},
{
"id": 15032,
"name": "Ubuntu 23",
"maxCpu": null,
"parentId": 15,
"created": "2023-05-22T14:56:11.93Z"
}
]
}
My first attempt using just a simple LinQ with a lambda expression was:
var licenses = await _repository.FindAll().Where(x => filter.Name.Contains(x.Name)).ToArrayAsync();
The problem with this query is that only works with exact matches (ex: "Windows 2019" or "Ubuntu 23"), but not partial matches.
Of course I could just iterate with a foreach loop and filter every element one by one, but I'd like to find a more elegant solution using LinQ, if possible.
Any suggestions?
Edit 1: Explanation of the problem described above.
What I'm trying to say with "my example query only works with exact matches" is that if I search, for example, ["Windows 2016"], or, another example, ["Windows 2012", "Ubuntu 23"] it will work, but with ["Windows 20"] or ["Ubunbtu", "Windows"] won't, because the match is not exact, and this is what my example does, just works with exact matches, so it works partially.
I think using .Any()
is helpful here.
var licenses = await _repository.FindAll().Where(x => filter.Name.Any(f => x.Name.Contains(f)).ToArrayAsync();
Since filter.Name
is also a list, it can use LINQ expressions. Also, f
should now be contained in x.Name
.
Hope that helps!