按关联项目过滤时获取 Sequelize 中的所有关联项目

问题描述 投票:0回答:1

我正在使用sequelize.js,我有两个表“媒体”和“标签”,其中一个媒体项目可以有多个标签,一个标签可以标记多个媒体项目(

tags.belongsToMany(media)
media.belongsToMany(tags)
)。

我倾向于通过标签查询媒体项目,所以

media.findAll({ include: { model: 'tags', where: { tagName: 'movie' } } }

问题是这样的(诸如

include: 'tags', where: { '$tags.tagName$': 'movie' }
之类的变体将仅包含与它们返回的所有媒体项的“标签”字段中的tagName匹配的标签。这不是我想要的。我想在上看到所有标签媒体项已返回,但具有与其关联的 tagName“电影”标签的媒体项。

sequelize 是否提供任何方法来做到这一点?

快速演示:

media.findOne({ include: { model: 'tags', where: { tagName: 'Pins' } } }

// Returns:
  {
    mediaId: 3555,
    checksum: 'xyz',
    fileType: 'image',
    extension: 'jpg',
    title: null,
    description: null,
    downloaded: true,
    downloadType: null,
    dateDownloaded: null,
    createdAt: '2023-12-02T19:51:50.000Z',
    updatedAt: '2023-12-08T01:46:09.000Z',
    tags: [ 
  {
    tagId: 26,
    tagName: 'Pins',
    parentTagId: null,
    createdAt: '2023-12-06T23:32:53.000Z',
    updatedAt: '2023-12-08T01:30:14.000Z',
    mediaTagMapping: {
      mappingId: 16919,
      mediaId: 3555,
      tagId: 26,
      createdAt: '2023-12-06T23:32:54.000Z',
      updatedAt: '2023-12-08T02:15:02.000Z'
    }
  },

 ]
  },



// Expected:

 {
    mediaId: 3555,
    checksum: 'xyz',
    fileType: 'image',
    extension: 'jpg',
    title: null,
    description: null,
    downloaded: true,
    downloadType: null,
    dateDownloaded: null,
    createdAt: '2023-12-02T19:51:50.000Z',
    updatedAt: '2023-12-08T01:46:09.000Z',
    tags: [ 
  {
    tagId: 26,
    tagName: 'Pins',
    parentTagId: null,
    createdAt: '2023-12-06T23:32:53.000Z',
    updatedAt: '2023-12-08T01:30:14.000Z',
    mediaTagMapping: {
      mappingId: 16919,
      mediaId: 3555,
      tagId: 26,
      createdAt: '2023-12-06T23:32:54.000Z',
      updatedAt: '2023-12-08T02:15:02.000Z'
    }
  },
  {
    tagId: 27,
    tagName: 'Beauty',
    parentTagId: null,
    createdAt: '2023-12-06T22:32:53.000Z',
    updatedAt: '2023-12-08T01:30:15.000Z',
    mediaTagMapping: {
      mappingId: 16919,
      mediaId: 3555,
      tagId: 26,
      createdAt: '2023-12-06T22:32:54.000Z',
      updatedAt: '2023-12-08T02:15:04.000Z'
    }
  },

 ]
  },

*/

注意:这个问题实际上之前就被问过,但那是 5 年前的事了,得到了 0 个回复,所以我不确定旧项目的刷新政策是什么。老问题的链接:在 Sequelize 中,如何按项目的多对多关联值过滤项目,并显示其所有关联值?

sequelize.js
1个回答
0
投票

我找到了一个(?)解决方案。解决方案是创建一个仅用于过滤的 second 关联,并包含两者:

// First association, this will return the tags as normal
sequelizeDatabase.models.media.belongsToMany(sequelizeDatabase.models.tags, {
    through: sequelizeDatabase.models.mediaTagMapping,
    uniqueKey: 'mappingId',
    foreignKey: 'mediaId',
    otherKey: 'tagId',
});

// Second association, this will return only matching tags
sequelizeDatabase.models.media.belongsToMany(sequelizeDatabase.models.tags, {
    through: sequelizeDatabase.models.mediaTagMapping,
    uniqueKey: 'mappingId',
    foreignKey: 'mediaId',
    otherKey: 'tagId',
    as: 'tagFilter'
});

运行它:


await sequelizeDatabase.models.media.findAll({
    include: [ {
            model: sequelizeDatabase.models.tags,
        }, {
            model: sequelizeDatabase.models.tags,
            required: true,
            as: 'tagFilter',
            where: {
                tagName: 'Beauty'
            }
        }
    ]
});

// Returns

{
  mediaId: 3589,
  checksum: '20b7c7af0ecdf1f61da2d78277e02ebad747a65428bbfa43ac86cd272c7f1a2a59019c0295f4c114032fdd4b69c8242e05be2ab9a5029e7ccc8b727e7d660e3a',
  url: null,
  fileType: 'image',
  extension: 'jpg',
  title: null,
  description: null,
  downloaded: true,
  downloadType: null,
  dateDownloaded: null,
  createdAt: '2023-12-02T19:51:51.000Z',
  updatedAt: '2023-12-08T01:46:09.000Z',
  tags: [
    {
      tagId: 26,
      tagName: 'Pins',
      createdAt: '2023-12-06T23:32:53.000Z',
      updatedAt: '2023-12-08T01:30:14.000Z',
      mediaTagMapping: [Object]
    },
    {
      tagId: 32,
      tagName: 'Me',
      createdAt: '2023-12-06T23:40:45.000Z',
      updatedAt: '2023-12-08T01:30:14.000Z',
      mediaTagMapping: [Object]
    },
    {
      tagId: 33,
      tagName: 'Beauty',
      createdAt: '2023-12-06T23:40:47.000Z',
      updatedAt: '2023-12-08T01:30:14.000Z',
      mediaTagMapping: [Object]
    },
    {
      tagId: 39,
      tagName: 'pfp/previous',
      createdAt: '2023-12-06T23:42:48.000Z',
      updatedAt: '2023-12-08T01:30:14.000Z',
      mediaTagMapping: [Object]
    }
  ],
  tagFilter: [
    {
      tagId: 33,
      tagName: 'Beauty',
      createdAt: '2023-12-06T23:40:47.000Z',
      updatedAt: '2023-12-08T01:30:14.000Z',
      mediaTagMapping: [Object]
    }
  ]
}

不幸的是,似乎必须在启动时定义关联,因为 Sequelize 似乎不允许您在没有预定义的情况下包含多个关联。

如果我没有收到任何更好的答案,我会在几天左右将此标记为解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.