【问题标题】:Query where there is at least 1 association, but return all查询至少有 1 个关联,但返回所有
【发布时间】:2019-05-07 10:42:46
【问题描述】:

我创建了这条记录,您可以看到它有 2 个标签 - tag1 和 tag2

{
  "id": "d87de1d9-b048-4867-92fb-a84dca59c87e",
  "name": "Test Name",
  "tags": [
    {
      "id": "fa0ca8fd-eff4-4e58-8bb0-a1ef726f01d4",
      "name": "tag1",
      "organizationId": "d87de1d9-b048-4867-92fb-a84dca59c87e",
      "updatedAt": "2018-12-05T18:53:56.867Z",
      "createdAt": "2018-12-05T18:53:56.867Z"
    },
    {
      "id": "66e758af-9907-4278-8c4f-f8fb2bf9aea9",
      "name": "tag2",
      "organizationId": "d87de1d9-b048-4867-92fb-a84dca59c87e",
      "updatedAt": "2018-12-05T18:53:56.867Z",
      "createdAt": "2018-12-05T18:53:56.867Z"
    }
  ],
  "updatedAt": "2018-12-05T18:53:56.860Z",
  "createdAt": "2018-12-05T18:53:56.860Z"
}

我想编写一个查询来查找包含tag1 的组织并返回包括所有标签的整个组织。

我目前有这个查询,它只返回与查询匹配的标签记录,而不是所有标签。

db.organization.findAll({
  include: {
    model: db.tag,
    where: { name: 'tag1' }
  }
})

它正在产生这个结果

[
  {
    "id": "3d03d74e-82ec-485e-aa29-abe9e8b0f0e9",
    "name": "Test Name",
    "createdAt": "2018-12-05T19:29:40.685Z",
    "updatedAt": "2018-12-05T19:29:40.685Z",
    "tags": [
      {
        "id": "75dc9cd2-5e20-4aa6-b86e-cbaa2c896d57",
        "name": "tag1", <-- NOTE THAT ONLY TAG1 IS IN THE RESULTS EVEN THOUGH THERE SHOULD BE ANOTHER TAG OBJECT RETURNED
        "createdAt": "2018-12-05T19:29:40.694Z",
        "updatedAt": "2018-12-05T19:29:40.694Z",
        "organizationId": "3d03d74e-82ec-485e-aa29-abe9e8b0f0e9"
      }
    ]
  }
]

如何编写查询来执行此操作?

【问题讨论】:

    标签: javascript node.js sequelize.js


    【解决方案1】:

    您想要做的是在表 OrganizationTag 上执行 右连接,但您实际上正在做的是 内连接(阅读更多关于加入here)

    sequelize 不支持右连接(请参阅已关闭的功能请求 here

    在我看来,你可以:

    • 运行原始 sql 查询(错误选项)
    • 通过 sequelize 执行聚合并使用节点过滤结果(ok 选项)

    const orgs = await db.organization.findAll({
      include: {
        model: db.tag,
      }
    });
    
    const result = orgs.filter(org => org.tags.some(tag => tag.name === 'tag1'))
    

    【讨论】:

    • 这不是 SQL 中的右连接,它需要一个子选择。
    【解决方案2】:

    我搜索了很多关于这个主题的内容,我认为最有效的方法(在这种情况下)是有一个用于过滤的基本关联和一个接收您的数据的关联

    关联文件

    // This is for filtering
    organization.hasMany(tag, {
      foreignKey: 'organizationId',
    });
    
    // This one is for receiving data after filtering
    organization.hasMany(tag, {
      foreignKey: 'organizationId',
      as: 'tags',
    });
    

    控制器

    const results = await db.organization.findAll({
      include: [{
        model: db.tag,
        where: { name: 'tag1' },
        attributes: [], // remove 'Tag' property from results
      }, {
        model: db.tag,
        as: 'tags',
      }],
    });
    
    console.log(results);
    

    console.log(results); 将返回:

    [
      {
        "id": "...",
        "name": "Organization Test Name",
        "createdAt": "...",
        "updatedAt": "...",
        // "Tag": [ // This property was removed by 'attributes: []'
        //   {
        //     "id": "...",
        //     "name": "tag1",
        //     "organizationId": "..."
        //     "createdAt": "...",
        //     "updatedAt": "...",
        //   },
        // ],
        "tags": [
          {
            "id": "...",
            "name": "tag1",
            "organizationId": "..."
            "createdAt": "...",
            "updatedAt": "...",
          },
          {
            "id": "...",
            "name": "tag1",
            "organizationId": "..."
            "createdAt": "...",
            "updatedAt": "...",
          }
        ]
      }
    ]
    

    来自 GitHub 的一些资源:Can't exclude association's fields from select statement in sequelize #3664

    【讨论】:

      【解决方案3】:

      不完整的方法是:

      tag.belongsTo(organization, {as: 'AllTags', foreignKey : 'organization_id' }); 
      // --- Add another association with alias ----- 
      
      db.organization.findAll({
          include: [{
              model: db.tag,
              where: { name: 'tag1' }
          },{
              model: db.tag,
              as : 'AllTags' //<----- HERE
          }]
      })
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-09-22
        • 2012-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多