如何通过关联查询sequelize模型,但包括所有相关对象?

时间:2017-12-05 20:23:44

标签: javascript node.js postgresql orm sequelize.js

尝试按所有关联的属性进行查询,但获取所有关联

# FAQs: { id: 1, name: 'How to do it?' }, { id: 2, name: 'How to FIX it?' }
# tags: { id: 1, slug: 'api' }, { id: 2, slug: 'beta' }
# taggings: { id: 1, faqId: 1, mainEntityId: 1, mainEntityType: 'faq' }, { id: 2, faqId: 1, mainEntityId: 2, mainEntityType: 'faq' }

const query = { slugs: ['api'] }
const foundFAQs = await this.models.FAQ.findAll({
  where: {
    '$taggings.tag.slug$': { $in: query.slugs },
  },
  include: [{
    model: this.models.Tagging,
    as: "taggings",           
    include: [{
      model: this.models.Tag,         
      as: 'tag',
    }],        
  }],
})

我的模型定义:

models.Tagging.belongsTo(models.Tag, { as: 'tag', onDelete: 'cascade' });
models.Tag.hasMany(models.Tagging, { as: 'taggings', onDelete: 'cascade' });
models.Tag.belongsToMany(models.FAQ, { through: models.Tagging, as: 'faqs' });
models.FAQ.hasMany(models.Tagging, { as: 'taggings', onDelete: 'cascade' });
models.FAQ.belongsToMany(models.Tag, { through: models.Tagging, as: 'tags' });

您期望发生什么?

我希望获取与TAG api相关联的所有常见问题解答,并提供其所有标记。

对象:     {     id:1,     名字:'怎么做?',     标签:[     {id:1,slug:'api'},     {id:2,slug:'beta'}     ]     }

实际发生了什么?

查询返回对象:     {       id:1,       名字:'怎么做?',       标签:[         {id:1,slug:'api'}       ]     }

输出

SELECT \"faq\".\"id\", \"faq\".\"name\", \"faq\".\"bankId\", \"faq\".\"priority\", 
\"faq\".\"publishedLocales\", \"faq\".\"createdAt\", \"faq\".\"updatedAt\", \"taggings\".\"id\" 
AS \"taggings.id\", \"taggings\".\"tagId\" AS \"taggings.tagId\", \"taggings\".\"locked\" 
AS \"taggings.locked\", \"taggings\".\"sdkId\" AS \"taggings.sdkId\", \"taggings\".\"guideId\" 
AS \"taggings.guideId\", \"taggings\".\"newsId\" AS \"taggings.newsId\", \"taggings\".\"faqId\" 
AS \"taggings.faqId\", \"taggings\".\"apiId\" AS \"taggings.apiId\", \"taggings\".\"createdAt\" 
AS \"taggings.createdAt\", \"taggings\".\"updatedAt\" AS \"taggings.updatedAt\", \"taggings->tag\".\"id\" 
AS \"taggings.tag.id\", \"taggings->tag\".\"name\" AS \"taggings.tag.name\", \"taggings->tag\".\"slug\" 
AS \"taggings.tag.slug\", \"taggings->tag\".\"tagType\" AS \"taggings.tag.tagType\", \"taggings->tag\".\"mainEntityId\" 
AS \"taggings.tag.mainEntityId\", \"taggings->tag\".\"createdAt\" 
AS \"taggings.tag.createdAt\", \"taggings->tag\".\"updatedAt\" 
AS \"taggings.tag.updatedAt\" FROM \"faqs\" AS \"faq\" INNER JOIN \"taggings\" 
AS \"taggings\" ON \"faq\".\"id\" = \"taggings\".\"faqId\" LEFT OUTER JOIN \"tags\" 
AS \"taggings->tag\" ON \"taggings\".\"tagId\" = \"taggings->tag\".\"id\" WHERE \"faq\".\"bankId\" = 'bank.csas' 
AND \"taggings->tag\".\"slug\" IN ('faq') ORDER BY \"faq\".\"priority\" DESC;

方言: postgres

方言版本: pg@^6.1.0

数据库版本: PostgreSQL 10.1

Sequelize版本: 4.23.2

使用最新版本测试:否(4.23.2)

节点 8.6.0

我不确定这是一个错误还是我做错了什么。

由于

2 个答案:

答案 0 :(得分:0)

您希望包含每条记录的所有相关数据,但会过滤这些相关数据的记录。您将希望获得Sequelize以生成类似于以下内容的SQL:

SELECT "faq"."id", ....
FROM "faqs" AS "faq"
INNER JOIN "taggings" AS "taggings" ON "faq"."id" = "taggings"."faqId"
LEFT OUTER JOIN "tags" AS "taggings->tag" ON "taggings"."tagId" = "taggings->tag"."id"
LEFT OUTER JOIN "tags" AS "taggings->tagdata" ON "taggings"."tagId" = "taggings->tagdata"."id"
WHERE "faq"."bankId" = 'bank.csas' AND "taggings->tag"."slug" IN ('faq')
ORDER BY "faq"."priority" DESC;

这样的事可能有用:

const foundFAQs = await this.models.FAQ.findAll({
  where: {
    '$taggings.tag.slug$': { $in: query.slugs },
  },
  include: [{
    model: this.models.Tagging,
    as: "taggings",           
    include: [{
      model: this.models.Tag,         
      as: 'tag',
    },{
      model: this.models.Tag,         
      as: 'tagdata',
    }],
  }],
})

这里的想法是,您正在执行要过滤的连接,然后是另一个连接以获取已过滤行的额外记录。

答案 1 :(得分:0)

今天这对我有用 - 嵌套的 includes

getReferralPlanForThisCode(parent, args, context) {
    let {referralCode} = args;
    return Promise.resolve()
        .then(() => {
            let referralPlan = connectors.ReferralPlans.findAll({
                include: [{
                    model: connectors.ReferralCodes,
                    where: {unique_referral_code: referralCode},
                    include: [{
                        model: connectors.epUserData, as: 'referrer',
                    }],
                }],
            })
            return referralPlan;
        })
        .then(referralPlan => {
            return referralPlan;
        })
        .catch((err) => {
            console.log(err);
        });
}