Something I often see in e-commerce websites is a sidebar with checkboxes for various filtering values. Many of these can be checked, and adding new values further narrows down your search.
I want to implement something similar for metadata pertaining to digital media. I have an array of possible filters, each of which is an object {nameOfProperty: ['Value1', 'Value2']}
. The idea is to return results that satisfy ALL of the criteria in an array of attributes {value: 'Value1', trait_type: 'NameOfProperty'}
.
See example:
const arr = [
{ metadata: { json: {
attributes: [
{ value: "Copycat Fridge Artist", trait_type: "Artist" },
{ value: "Fridges Vol. 2", trait_type: "Playlist" },
{ value: "Fridges Playlist", trait_type: "Playlist" },
{ value: "Image", trait_type: "Artwork Type" }
]
},
{ metadata: { json: {
attributes: [
{ value: "Copycat Fridge Artist", trait_type: "Artist" },
{ value: "Fridges Vol. 1", trait_type: "Collection" },
{ value: "Videos Playlist", trait_type: "Playlist" },
{ value: "Video", trait_type: "Artwork Type" }
]
},
{ metadata: { json: {
attributes: [
{ value: "Cool Original Artist", trait_type: "Artist" },
{ value: "Fridges Vol. 1", trait_type: "Collection" },
{ value: "Videos Playlist", trait_type: "Playlist" },
{ value: "Video", trait_type: "Artwork Type" }
]
}
];
and an array of filters
filters: [{Artwork Type: ['Image', 'Video']},
{Playlist: ['Videos Playlist']},
{Artist: ['Cool Original Artist']}]
In this scenario, I want to see images or videos, only from the Videos Playlist and then only ones by Cool Original Artist. The filter should return arr[2].
The filters can be many and varied, and not every item in the array has the name number of attributes.
If there is a name for this kind of search/filter I am not aware of it, so apologies if this has been asked before. It's something I've encountered many times, but never tried to code myself, and I'm struggling!
In general I filter the arr
values in a reducer.
const arr = [
{ metadata: { json: {
attributes: [
{ value: "Copycat Fridge Artist", trait_type: "Artist" },
{ value: "Fridges Vol. 2", trait_type: "Playlist" },
{ value: "Fridges Playlist", trait_type: "Playlist" },
{ value: "Image", trait_type: "Artwork Type" }
]
}}},
{ metadata: { json: {
attributes: [
{ value: "Copycat Fridge Artist", trait_type: "Artist" },
{ value: "Fridges Vol. 1", trait_type: "Collection" },
{ value: "Videos Playlist", trait_type: "Playlist" },
{ value: "Video", trait_type: "Artwork Type" }
]
}}},
{ metadata: { json: {
attributes: [
{ value: "Cool Original Artist", trait_type: "Artist" },
{ value: "Fridges Vol. 1", trait_type: "Collection" },
{ value: "Videos Playlist", trait_type: "Playlist" },
{ value: "Video", trait_type: "Artwork Type" }
]
}}}
];
const filters = [
{ "Artwork Type": ["Image", "Video"] },
{ Playlist: ["Videos Playlist"] },
{ Artist: ["Cool Original Artist"] }
];
// reduce the arr by matching with each filter object
const result = filters.reduce((remaining, curr) => {
// assign filter attribute name and values
const [name, values] = Object.entries(curr)[0];
// do filtering
return remaining.filter(({metadata: { json: {attributes}}}) =>
attributes.find((a) => a.trait_type === name && values.includes(a.value))
);
}, arr);
console.log(result);