代码之家  ›  专栏  ›  技术社区  ›  amaster

使用Sequelize和Multiple OR运算符动态构建Where子句

  •  0
  • amaster  · 技术社区  · 4 年前

    所需的MySQL查询:

    SELECT
      *
    FROM
      myTable
    WHERE 
      (
        JSON_CONTAINS(access,'"a"','$.owner') OR
        JSON_CONTAINS(access,'"b"','$.owner')
      ) AND
      (
        JSON_CONTAINS(access,'"c"','$.moderator') OR
        JSON_CONTAINS(access,'"d"','$.moderator')
      )
    

    动态构建过滤器的一些逻辑片段:

    const args = {x: ["a", "b"], y: ["c", "d"]}
    let where = {}
    // more code
    if (args.x && Array.isArray(args.x)) {
      const orWhere = args.x.map(x => sequelize.fn('JSON_CONTAINS', sequelize.col('access'), `"${x}"`,'$.owner'))
      where = {
        ...where,
        [Op.or]: orWhere
      }
    }
    if (args.y && Array.isArray(args.y)) {
      const orWhere = args.y.map(y => sequelize.fn('JSON_CONTAINS', sequelize.col('access'), `"${y}"`,'$.moderator'))
      where = {
        ...where,
        [Op.or]: orWhere
      }
    }
    // more code
    db.contacts.findAll({where})
    

    这样做的问题是 args.x args.y [Op.or]: orWhere from第二个语句重写where对象中已有的内容。

    我已经通读了 Sequelize WHERE docs ,但尚未找到解决方案。如果我不做复杂的JSON查询函数,这会很简单。

    注意 :是的,我正在阻止注入,但为了缩短代码,故意省略了该部分

    编辑: 正如@Anatoly建议的,使用续集.fn而不是文字,但留下了相同的覆盖条件 where[Op.or] 在第二个if条件下

    0 回复  |  直到 4 年前
        1
  •  1
  •   Anatoly    4 年前

    你可以用[操作和]和你以前一样[手术室]:

    if ((args.x && Array.isArray(args.x)) ||
        (args.y && Array.isArray(args.y))) {
      where[Op.and] = []
      if (args.x && Array.isArray(args.x)) {
        const orWhere = args.x.map(x => sequelize.fn('JSON_CONTAINS',   sequelize.col('access'), `"${x}"`,'$.owner'))
        where[Op.and].push({
          [Op.or]: orWhere
        })
      }
      if (args.y && Array.isArray(args.y)) {
        const orWhere = args.y.map(y => sequelize.fn('JSON_CONTAINS', sequelize.col('access'), `"${y}"`,'$.moderator'))
        where[Op.and].push({
          [Op.or]: orWhere
        })
      }
    }