Sequelize.js s、 addScope('defaultScope'{ 包括:[ { 协会:"场地",, 包括:[ { 协会:'地区', 包括:[ { 协会:"类别",, 属性:[],//不需要结果中的类别 其中:{ //仅获取区域标记 类别:“区域” } } ], } ] }, ], 订单:[“标题”] }, { 覆盖:真 }) }

Sequelize.js s、 addScope('defaultScope'{ 包括:[ { 协会:"场地",, 包括:[ { 协会:'地区', 包括:[ { 协会:"类别",, 属性:[],//不需要结果中的类别 其中:{ //仅获取区域标记 类别:“区域” } } ], } ] }, ], 订单:[“标题”] }, { 覆盖:真 }) },sequelize.js,Sequelize.js,这是可行的,因为我在我的场地实例中得到了一个“区域”数组include有一个as选项,但似乎只适用于模型,因此重复关联(标记/区域)似乎是描述这一点的唯一方法,它看起来并不十分枯燥(更不用说从维护角度来看可能会令人困惑) 这个vention表只有一个区域标记关联,但其他表有多个关联,所有关联都基于标记,但针对不同的类别,因此我可以看到我会一次又一次地遇到这个问题,而且代码味道很差 就我所见,使用作用域和查询方法的选项对我来说没有区别,而且我可以看到,我可能会选择使用多个作用域,以便在不需要数据时

这是可行的,因为我在我的场地实例中得到了一个“区域”数组
include
有一个
as
选项,但似乎只适用于
模型
,因此重复关联(
标记
/
区域
)似乎是描述这一点的唯一方法,它看起来并不十分枯燥(更不用说从维护角度来看可能会令人困惑)

这个
vention
表只有一个区域标记关联,但其他表有多个关联,所有关联都基于标记,但针对不同的类别,因此我可以看到我会一次又一次地遇到这个问题,而且代码味道很差

就我所见,使用作用域和查询方法的选项对我来说没有区别,而且我可以看到,我可能会选择使用多个作用域,以便在不需要数据时(或使用覆盖限制默认作用域)不会生成超过必要的联接

我相信有人可能会说,现有的表结构并不理想,它的遗留问题,我需要适应它的缺点,而不必把它们带到新的实现中去。一旦遗留代码消失,就有机会重构表结构


到目前为止,我还没有看到有必要描述这种相反的关系,但这可能是因为到目前为止,我只是触及表面,评估Sequelize是否符合我的需要。一种选择是使用原始MYSQL驱动程序,仅复制PHP应用程序中的查询,但其中一个方面是PHP应用程序的SQL实现不一定是最优的。

因此,您有三个表:
场馆
标记
标记
。此外,
场馆
标签
之间存在N:M关系,由直通表(有时也称为连接表或联合表)
场馆相关标签
处理。
tag\u categories
tags
之间也存在1:N的关系(这意味着每个标签都有一个类别,同一类别可以应用于多个标签)

您希望仅查询至少有一个类别为“区域”的标记的场馆,并且您希望每个获得的场馆对象都有一个额外的字段
“区域”
,该字段是一个标记数组,仅包含类别为“区域”的该场馆标记

模型定义 为了运行我自己的代码,我将使用sequelize和本地postgres数据库进行测试

为了完整起见,我将使用的模型如下。它们与您的相同,但我省略了
id
字段,并在适用的情况下添加了
参考
字段。我的全部代码将在一个文件中,但您可以保留每个文件一个表的设置

const Sequelize=require(“Sequelize”);
const sequelize=新的sequelize(“postgres://postgres@localhost:5432/testdb“,{方言:“postgres”});
const vention=sequelize.define('ventions'{
标题:Sequelize.STRING(255)
},{tableName:'场馆',时间戳:false});
const Tag=sequelize.define('tags'{
description:Sequelize.STRING(255),
标签\类别\标识:{
类型:Sequelize.INTEGER(10).无符号,
参考资料:{model:“tag_categories”,key:“id”}
}
},{tableName:'tags',时间戳:false});
const TagCategory=sequelize.define('tag_categories'{
类别:Sequelize.STRING(64)
},{tableName:'tag_categories',时间戳:false});
const vention\u Tag=sequelize.define('vention\u relatesto\u tags'{
场地编号:{
类型:Sequelize.INTEGER(10).无符号,
参考资料:{模型:“场馆”,键:“id”}
},
标签号:{
类型:Sequelize.INTEGER(10).无符号,
参考:{model:“tags”,key:“id”}
}
},{tableName:'vention_relatesto_tags',时间戳:false});
关系 您使用别名在表之间建立了一些复杂的关系。最糟糕的是,在同一个模型之间创建了两个不同别名的多个关系。基于你的目标,我理解你为什么要这么做,但至少可以说这很让人困惑。所以我不会那么做。获取所需字段的解决方案将有所不同:我们不会试图让sequelize本身使用所需的字段名生成所需的确切结构,而是使用sequelize获取数据,然后使用纯JavaScript对其进行整合

vention.belongtomany(标记,{通过:vention\u标记,外键:'vention\u id',其他键:'Tag\u id'});
Tag.belongTomany(地点,{通过:地点标签,外键:'Tag_id',其他键:'vention_id'});
hasMany(Tag,{foreignKey:'Tag_category_id'});
belongsTo(TagCategory,{foreignKey:'Tag_category_id'});
用测试值填充数据库 这一部分仅用于完整性,向您展示我如何使用虚拟值填充自己的数据库,以测试自己的代码。我决定创建两个不同的
标记类别
,其中一个称为
“Region”
。此外,我还创建了四个标记,其中两个被分类为
“Region”
,还有两个
场馆
,第一个带有所有标记,第二个没有区域分类标记。见下文

函数设置(){
返回sequelize.sync({force:true})
.然后(()=>保证([
创建({category:“Region”}),
标记
[
  {
    "id": 1,
    "title": "Venue 1",
    "regions": [
      {
        "id": 4,
        "description": "Tag 4",
        "tag_category_id": 1
      },
      {
        "id": 3,
        "description": "Tag 3",
        "tag_category_id": 1
      }
    ]
  }
]