createAdvancedFilter for nested object in nested array with several linked criteria
Hello,
First of all, thanks a lot for this great library, it's nice to play with it.
I'm stuck with a specific multi-criteria filter. Here is a sample of what I want to filter :
const contacts = [
{
"contactId": "2173",
"codes": [
{
"year": "2010",
"category": "CIE",
"group": "CIO"
},
{
"year": "2007",
"category": "CIE",
"group": "CIO"
},
{
"year": "2008",
"category": "PRO",
"group": "COL"
}
]
},
{
"contactId": "11982",
"codes": [
{
"year": "2017",
"category": "LIS",
"group": "FES"
}
]
},
{
"contactId": "12146",
"codes": [
{
"year": "2019",
"category": "LIS",
"group": "FES"
}
]
}
]
I need to filter the contacts by category+group and optionally with a minimum year and a maximum year to add filter by year within each code.
I tried something like this but value cannot be deconstructed:
const filter = handler.createAdvancedFilter( 'codes', (row, value) => {
const [category, group, minYear, maxYear] = value.split(';')
if (!minYear && !maxYear) {
return row.codes?.some((c) => c.category === category && c.group === group)
} else return row.codes?.some(
(c) => c.category === category && c.group === group && c.year >= minYear && c.year <= maxYear
)
}
and then
filter.set(`${category}-${group}-${minYear}-${maxYear}`)
I cannot create one advanced filter by each category, group and year as I need to filter all these criteria inside each code from the contact's code.
Did I miss something?
I could still change the model, but even if I concat category+group+year, I still have to find year from between 2 dates.
Hello,
createAdvancedFilter is useful to add a multiple criteria filter when you have values of type string or number. It has limitations for nested objects.
According to your data sample, I would suggest to create 3 different filters instead.
Contacts would be filtered if these 3 criteria are true. For example:
WHERE group IN ('CIO', 'COL')
AND category IN ('CIE', 'LIS')
AND year BETWEEN 2007 AND 2020
Group filter:
type Code = { year: string, category: string, group: string }
const filter = handler.createFilter('codes', (entry: Code[], values: string[]) => {
const groups = entry.map(item => item.group)
for(const value of values) {
if (groups.includes(value)) {
return true
}
}
return false
})
filter.set(['CIO', 'COL'])
Category filter:
const filter = handler.createFilter('codes', (entry: Code[], values: string[]) => {
const categories = entry.map(item => item.category)
for(const value of values) {
if (categories.includes(value)) {
return true
}
}
return false
})
filter.set(['CIE', 'LIS'])
Year filter:
const filter = handler.createFilter('codes', (entry: Code[], value: number[]) => {
// get minYear and maxYear as number[]
const years = entry.map(item => Number(item.year))
const [minYear, maxYear] = [Math.min(...years), Math.max(...years)]
// check
const [min, max] = value
return minYear >= min && maxYear <= max
})
filter.set([2007, 2020])
I don't find another way to achieve this.
Hello, made me think a lot, I didn't find another way neither. Thank you very much vincjo!
Hello, thx for your reply. I will probably try this use case with the next version