2

Have found similar answers through the search, but I can quite crack this one. I'm using Node, Express, and Sequelize. I have a working query (included below) but I would like to modify it to support a dynamic number playlistThemes, depending on the number of themes a user selects in the client, instead of always using the four as I've done below.

I'll need to loop over the playlistThemes object (or req.body.selectedThemes) and dynamically generate similar [Op.gt] queries for each theme. I'll then need to add those to my where clause, though I could probably break it out into steps?

I'm not sure, any ideas?

builder.post('/', async (req, res) => {
  let playlistThemes = Object.fromEntries(Object.entries(req.body.selectedThemes));
  customPlaylist = await db.songs.findAll({
    where: {
      [Op.and]: [
        { intensity: { [Op.between]: [req.body.intensity[0], req.body.intensity[1]] } }, 
        { dissonance: { [Op.between]: [req.body.dissonance[0], req.body.dissonance[1]] } },
        { peculiarity: { [Op.between]: [req.body.peculiarity[0], req.body.peculiarity[1]] } },
        // Want a dynamic number of the items below (min of 1 theme, max of 5)
        { [playlistThemes[0].name]: { [Op.gt]: [playlistThemes[0].weight] } }, 
        { [playlistThemes[1].name]: { [Op.gt]: [playlistThemes[1].weight] } }, 
        { [playlistThemes[2].name]: { [Op.gt]: [playlistThemes[2].weight] } }, 
        { [playlistThemes[3].name]: { [Op.gt]: [playlistThemes[3].weight] } }, 
    ]}
  });
  return res.send(customPlaylist);
  
});
brickandbone
  • 375
  • 1
  • 3
  • 7

1 Answers1

2

In order to solve this you need convert playlistThemes in an array of objects (or dictionary) with the flowing format: { [playlistThemes[i].name]: { [Op.gt]: playlistThemes[i].weight] } }

To solve this you can use the array map function. For each element of the list you create an object with the desired format.

The first step is to do the mapping:

const themes = playlistThemes.map((theme) => {
  return { [theme.name]: { [Op.gt]: [theme.weight] } }
})

The second step is to add each element in the new array to the search. We can copy each element of the new array using ...themes. This is useful to merge arrays.

The final code is the following:

  builder.post('/', async (req, res) => {
  let playlistThemes = Object.fromEntries(Object.entries(req.body.selectedThemes));

  const themes = playlistThemes.map((theme) => {
    return { [theme.name]: { [Op.gt]: [theme.weight] } }
  })

  customPlaylist = await db.songs.findAll({
    where: {
      [Op.and]: [
        { intensity: { [Op.between]: [req.body.intensity[0], req.body.intensity[1]] } }, 
        { dissonance: { [Op.between]: [req.body.dissonance[0], req.body.dissonance[1]] } },
        { peculiarity: { [Op.between]: [req.body.peculiarity[0], req.body.peculiarity[1]] } },
        ...themes
        ]}
      });
    return res.send(customPlaylist);
   });