查询至少有1个关联的地方,但返回全部

时间:2018-12-05 19:31:44

标签: javascript node.js sequelize.js

我创建了此记录,您可以看到它具有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"
      }
    ]
  }
]

如何编写查询来做到这一点?

3 个答案:

答案 0 :(得分:4)

不完整的方法是:

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
    }]
})

答案 1 :(得分:4)

我在这个问题上进行了很多搜索,我认为最有效的方法(在这种情况下)是建立基本的过滤关联并接收数据

关联文件

// 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

答案 2 :(得分:1)

您想要做的是在表OrganizationTag上执行右连接,但是您实际要做的是内部连接 (了解有关加入here的更多信息)

sequelize不支持右连接(请参见封闭功能请求here

我的看法,您可以:

  • 运行原始sql查询(错误选项)
  • 使用节点(确定选项)通过序列化和过滤结果来执行聚合

const orgs = await db.organization.findAll({
  include: {
    model: db.tag,
  }
});

const result = orgs.filter(org => org.tags.some(tag => tag.name === 'tag1'))