The desired MySQL query:
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')
)
A snippet of some of the logic that dynamically builds the filters:
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})
The problem with doing this is that when args.x and args.y are both provided then the [Op.or]: orWhere from the second statement overrides what is already in the where object.
I have read through the Sequelize WHERE docs, but have yet to find a solution. It would be simple if I was not doing complex JSON query functions.
NOTE: Yes, I am preventing against injection but that part is left out intentionally to shorten the code
EDIT: as @Anatoly suggested, use sequelize.fn instead of literal, but left with the same condition of overwriting where[Op.or] in second if condition