首页 > 解决方案 > Sequelize:如何利用多个运算符创建带有排除子句的对象提取

问题描述

我在使用 MySQL 的 NodeJS/Express/Angular7 应用程序中使用 Sequelize 5。

我有一个图像表,通过连接表与关键字表具有双向 hasMany 关系。

我想在 ID [ kewordsAnd ] 数组中查找包含关键字 ID 的所有图像,不包括在数组中包含关键字 ID 以排除 [ keywordsNot ] 的图像。

现在的代码如下:

Image.findAll({
  include: [ {
    model: Keywords,
    as: 'Keywords',
    attributes: ['id', 'name'],
    where: {
      id: {
        [Op.and]: [
          { [Op.in]: keywordsAnd },
          { [Op.notIn]: keywordsNot }
        ]
      }
    }
  } ]
});

这会正确获取所有在关键字和数组中具有 ID 的图像,但关键字非数组被完全忽略。

这是生成的 SQL(为可读性添加了换行符)

const objectsAnd:  [ 430 ]
const objectsNot:  [ 779 ]
Executing (default): 

SELECT `image`.`id`, `image`.`status`, `image`.`image_type`, `image`.`embed`, 
`image`.`raw_path`, `image`.`thumb_path`, `image`.`detail_path`, `image`.`story_title`, 
`image`.`image_title`, `image`.`original_filename`, `image`.`description`, 
`image`.`geo_info`, `image`.`year_taken`, `image`.`credit_info`, 
`image`.`width`, `image`.`height`, `image`.`format`, `image`.`duration`, 
`image`.`created_at` 

AS `createdAt`, `image`.`updated_at` AS `updatedAt`, `keywords`.`id` AS `keywords.id`, 
`keywords`.`name` AS `keywords.name`, `keywords`.`created_at` AS `keywords.createdAt`, 
`keywords`.`updated_at` AS `keywords.updatedAt`, `keywords->image_keywords`.`id` AS 
`keywords.image_keywords.id`, `keywords->image_keywords`.`image_id` AS 
`keywords.image_keywords.image_id`, `keywords->image_keywords`.`keyword_id` AS 
`keywords.image_keywords.keyword_id`, `keywords->image_keywords`.`created_at` AS 
`keywords.image_keywords.createdAt`, `keywords->image_keywords`.`updated_at` AS 
`keywords.image_keywords.updatedAt` 

FROM `image` AS `image` INNER JOIN ( `image_keywords` AS `keywords->image_keywords` 
INNER JOIN `keywords` AS `keywords` 
ON `keywords`.`id` = `keywords->image_keywords`.`keyword_id`) 
ON `image`.`id` = `keywords->image_keywords`.`image_id` 
AND (`keywords`.`id` IN (430) AND `keywords`.`id` NOT IN (779));

我不清楚这是否是我如何构建查询的问题,或者一个错误,或者我对它应该如何工作的完全误解,但我真的希望得到一些指导。

标签: mysqlnode.jsangularexpresssequelize.js

解决方案


鉴于下面的示例数据,您是否只希望得到图像 1(而不是图像 2)的结果?

image id    keyword id
1           430
2           430
2           709

如果是这样,那么问题出在您的查询上。您需要选择具有关键字 id 709 的图像 id并将其用作 NOT IN 语句的基础。


推荐阅读