I'm using react+ nextJS and grabbing static objects, "posts". The goal is to create a "related posts" component on each post which grabs three posts that contain at least one of the categories. Here's what it looks like when I run a map on AllPosts (I trimmed it down so it's easier to read):
const allPosts = getAllPosts(['title', 'categories'])
[{
title: 'Black History Month: A History in Black Cinematography',
categories: [ 'education' ]
}
{
title: 'New Kid on the Block',
categories: [ 'announcements', 'new hires' ]
}
{
title: 'Olivia Boldt: Bol(d)ting Into the Bakery',
categories: [ 'announcements', 'new hires' ]
}
{
title: 'PDF Presets in Adobe Illustrator. Which one should you use?',
categories: [ 'Research', 'education' ]
}
{
title: 'Pixel Bakery does XYZ',
categories: [ 'press & media', 'announcements' ]
}
{
title: 'Recipe for Success: Mix Adaptability and Confidence (together, in a medium sized bowl)',
categories: [ 'editorial', 'second cat', 'third cat' ]
}
{
title: 'Samee Callahan: A Winding Path to Excitement',
categories: [ 'announcements', 'new hire' ]
}
{
title: 'Sophia Stueven’s Favorite Way to Breathe',
categories: [ 'announcements', 'new hires' ]
}]
So far, I can get it to match posts that have the same [0] category, but I can't wrap my brain around how to compare all of them:
const allPosts = getAllPosts(['title', 'categories'])
const SearchCat = post.categories[0]
const matchingPosts = allPosts.filter((item) => item.categories[0] === SearchCat)
console.log(matchingPosts)
yields:
[{
title: 'An Introduction to our Technology Stack',
categories: [ 'announcements', 'new hire' ]
},
{
title: 'New Kid on the Block',
categories: [ 'announcements', 'new hires' ]
},
{
title: 'Olivia Boldt: Bol(d)ting Into the Bakery',
categories: [ 'announcements', 'new hires' ]
},
{
title: 'Samee Callahan: A Winding Path to Excitement',
categories: [ 'announcements', 'new hire' ]
},
{
title: 'Sophia Stueven’s Favorite Way to Breathe',
categories: [ 'announcements', 'new hires' ]
}]
How do I go about adding another filter layer that doesn't care about the position the category match is in and only require one of them to match?
It looks like you have some further questions so here is an example tailored to your use case.
- How do I make the search ignore case sensitivity
You can map the currentPost.categories array to a Set converting each category toUpperCase() and do the same in the filter() call.
post.categories.some(category => searchCategories.has(category.toUpperCase()));
- How do I exclude the current post from the returned list
You can add a condition to the filter to look for the currentPost before looking for categories. (here using title but perhaps you have an id or other unique property you can use instead).
- Typescript doesn't like .some: "Property 'some' does not exist on type 'string'"
That's because some() is an array method and it seems you are trying to call it on a string.
const currentPost = {
title: 'New Kid on the Block',
categories: ['Announcements', 'new hires']
};
// const allPosts = getAllPosts(['title', 'categories'])
const allPosts = [{title: 'Black History Month: A History in Black Cinematography', categories: ['education']}, {title: 'New Kid on the Block', categories: ['announcements', 'New Hires']}, {title: 'Olivia Boldt: Bol(d)ting Into the Bakery', categories: ['announcements', 'New Hires']}, {title: 'PDF Presets in Adobe Illustrator. Which one should you use?', categories: ['Research', 'education']}, {title: 'Pixel Bakery does XYZ', categories: ['press & media', 'announcements']}, {title: 'Recipe for Success: Mix Adaptability and Confidence (together, in a medium sized bowl)', categories: ['editorial', 'second cat', 'third cat']}, {title: 'Samee Callahan: A Winding Path to Excitement', categories: ['announcements', 'new hire']}, {title: 'Sophia Stueven’s Favorite Way to Breathe', categories: ['announcements', 'new hires']}];
// Map the currentPost categories array to a Set for lookup in the filter
const searchCategories = new Set(currentPost.categories.map(category => category.toUpperCase()));
const matchingPosts = allPosts.filter(post => {
// If the currently iterated post title matches the currentPost return false (filter it out);
if (post.title === currentPost.title) {
return false;
}
// Otherwise, check if the currently iterated post has some() categories in common with currentPost
return post.categories.some(category => searchCategories.has(category.toUpperCase()));
});
console.log('Current Post:\n');
console.log(currentPost);
console.log('Matching Posts:\n');
console.log(matchingPosts);