求助sequlize ORM大佬来帮忙

目前有个组合查询的需求

image.png

想通过这种字段组合的方式来进行查询
如果是拼字符串还相对简单,直接连续拼接就可以 XX AND XX OR XXX 就可以了
但是想通过sequelize 提供的方法去拼就不会了

直接上代码 这是我自己写的,问题很多 BUG也很多
传参就是 ['and', '字段名', '='] 或者 ['or', '字段名', 'like']

if (where[w].length > 0) {
                for (let i = 0; i < where[w].length; i++) {
                    let _item = where[w][i]
                    let _item_1 = where[w][i-1]
                    if (_item[0] == 'AND' || _item[0] == 'OR' || _item[0] == 'NOT') {
                        if (_item[0] == 'AND') {
                            if (_item[3] == 'equals') {
                                _where_arr[_item[1]] = _item[2]
                            } else if (_item[3] == 'like') {
                                _where_arr[_item[1]] = {
                                    [_this.sequelize_op.like]: '%' + _item[2] + '%'
                                }
                            }
                        } else if (_item[0] == 'OR') {
                            if (_item[3] == 'equals') {
                                let _p = {};
                                _p[_item[1]] = {
                                    [_this.sequelize_op.eq]: _item[2]
                                }
                                let _p1 = {};
                                if ((i-1) == 0) {
                                    _p1[_item_1[0]] = {
                                        [_this.sequelize_op.eq]: _item_1[1]
                                    }
                                } else {
                                    _p1[_item_1[1]] = {
                                        [_this.sequelize_op.eq]: _item_1[2]
                                    }
                                }
                                let _or = {
                                    [_this.sequelize_op.or]: [_p, _p1]
                                }
                                Object.assign(_where_arr, _or)
                            } else {
                                let _p = {};
                                _p[_item[1]] = {
                                    [_this.sequelize_op.eq]: '%' + _item[2] + '%'
                                }
                                let _p1 = {};
                                if ((i-1) == 0) {
                                    _p1[_item_1[0]] = {
                                        [_this.sequelize_op.eq]: '%' + _item_1[1] + '%'
                                    }
                                } else {
                                    _p1[_item_1[1]] = {
                                        [_this.sequelize_op.eq]: '%' + _item_1[2] + '%'
                                    }
                                }
                                let _or = {
                                    [_this.sequelize_op.or]: [_p, _p1]
                                }
                                Object.assign(_where_arr, _or)
                            }
                        }

                        if (_item[0] == 'NOT') {
                            _where_arr[_item[1]] = {
                                [_this.sequelize_op.not]: _item[2]
                            }
                        }

                    } else {
                        if (_item[2] == 'equals') {
                            _where_arr[_item[0]] = _item[1]
                        } else if (_item[2] == 'like') {
                            _where_arr[_item[0]] = {
                                [_this.sequelize_op.like]: '%' + _item[1] + '%'
                            }
                        }
                    }
                    
                }
                
            }

想问问各位大佬这种应该怎么写

阅读 2.2k
1 个回答

为什么你会写的这么复杂呢?拿findOne 来说:

    let literal = Sequelize.literal(`( 字段a != 0 or 字段d != 0)`);
    let where = {'字段c' : "xxxx" , [Op.and] : literal , '字段b':{ [Op.like] : '%xxx%'} }
    let params = {
    };
    if(Object.keys(where).length != 0){
        params['where'] = where;
    }
    if(attributes[0] != 'all'){
        params['attributes'] = attributes;
    }
    let item = await Test.findOne(params);

这个只是个示例,具体的按照需求来写,但是已经基本可以使用sequelize Op 查询API,不用自己去弄那么复杂的组装。sequelize 查询使用文档

2021-12-02 更
按照你的最新的图只能给一些建议了:

1:那个查询条件,最好先整理一下,如果in , and ,or等其他是可以任意组合的话,其实这里可能有些不必要,因为有时候选了多个最后的结果和只选某一两个的条件是一样,任意选可能增加逻辑处理的麻烦,也可能给前端造成困扰,也不是那么必要。

2:如果字段是可以任意选择,在字段非常多的时候,也是有可能不是那么必要的,一般需要查看的东西是比较常用重要的那些,有一些很少用的可以要的时候再给它就好了,只给一些特定的字段给前端查就好了,比如这样:
image.png

字段固定下来了,逻辑就会简化多了。

最后就是整理成

where = {'字段c' : "xxxx" , [Op.and] : literal , '字段b':{ [Op.like] : '%xxx%'} }

这样就可以了。

2021-12-02 晚更

//前端组装成这样的数据:
let list = [
    {
        "field" : "name",
        "value" : "张三",
        "op" : 'and',
        "action" : 'like'
    },
    {
        "field" : "age",
        "value" : 18,
        "op" : 'and',
        "action" : 'eq'
    }
]

//如果 and 和 or 在一起循环遍历不好处理,可以先根据op把数组拆分,变成几个数组,分别拼好and 和 or的,最后再拼在一起(思路2)

let where = {};
for (const {field , value , action , op} of list) {

    //这里还可以判断op再进去判断action(思路1)

    if(action == 'like'){
        where[field] = { [Op.like] : `%${value}%`} 
        // where[field] = { } 
    }else{
        where[field] = value;
    }
}
console.log(where)
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题