使用 Sequelize 根据请求正文中的项目数创建一个动态的 where 子句?

Use Sequelize to create a dynamic where clause based on number of items in the request body?

通过搜索找到了类似的答案,但我可以破解这个。我正在使用 Node、Express 和 Sequelize。我有一个工作查询(包含在下面),但我想修改它以支持动态数字播放列表主题,具体取决于用户在客户端中选择的主题数量,而不是像我在下面所做的那样始终使用四个。

我需要遍历 playlistThemes 对象(或 req.body.selectedThemes)并为每个主题动态生成类似的 [Op.gt] 查询。然后我需要将它们添加到我的 where 子句中,尽管我可能会将其分解为多个步骤?

我不确定,有什么想法吗?

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);
  
});

为了解决这个问题,您需要将 playlistThemes 转换为具有流动格式的对象数组(或字典): { [playlistThemes[i].name]: { [Op.gt]: playlistThemes[i].weight] } }

要解决此问题,您可以使用 array map function。为列表中的每个元素创建一个具有所需格式的对象。

第一步是做映射:

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

第二步是将新数组中的每个元素添加到搜索中。我们可以使用 ...themes 复制新数组的每个元素。这对 merge arrays.

很有用

最终代码如下:

  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);
   });