我有一个具有多个链接关联的模型,如下所示:
Epci -> have many ->
公社-> have one ->
出发的-> have one ->
地区
我正在尝试检索Epci
及其相关的Regions
行,结果如下:
[
{
id: 1,
name: 'EPCI 1',
regions: [ // [1, 2] is also an acceptable format
{ id: 1 },
{ id: 2 }
]
}
]
目前,我取得了如下结果:
[
{
id: 1,
name: 'EPCI 1',
communes: [
{
id: 1,
departement: {
id: 1,
region: {
id: 1
}
}
},
{
id: 2,
departement: {
id: 1,
region: {
id: 1
}
}
},
{
id: 3,
departement: {
id: 2,
region: {
id: 2
}
}
},
]
}
]
通过此呼叫:
Epci.findAll({
attributes: [
'id',
'name',
],
include: [{
model: Commune,
attributes: ['id'],
include: [{
model: Departement,
attributes: ['id'],
include: [{
model: Region,
attributes: ['id'],
}],
}],
}],
})
是否有一种使用Regions
函数直接检索关联的(和不同的)findAll
的方法?试图使用Virtual
列和某种别名,但没有成功...
(我正试图避免对每个检索到的行运行查询)
当前的临时(?)解决方案(使用Sequelize TypeScript进行顺便说一句):
当前目标是检索一个简单的Regions数组,并清理Sequelize返回的“ communes”树属性的Epci结果。
因此,我们执行请求并检索所需的数据,然后使用Javascript转换结果。
Epci.findAll({
attributes: [
'id',
'name',
],
include: [{
model: Commune,
attributes: ['id'],
include: [{
model: Departement,
attributes: ['id'],
include: [{
model: Region,
attributes: ['id'],
}],
}],
}],
}).map((row: Epci) => {
// Retrieve plain object
const plain = row.get({ plain: true });
// Rebuild (retreive, unique) the regions property (declared as Virtual in the Epci model -- important).
plain.regions = plain.communes.map(commune => {
return commune.departement.region.id;
}).filter((id, index, self) => {
return self.indexOf(id) === index;
});
// Remove the communes property.
delete plain.communes;
// Rebuild Epci instance with the modified plain object
const instance = this.repository.build(plain);
// Then return instance
return instance;
});
使用Postgresql数组函数的公认且高效的解决方案:
sequelize.query(`
SELECT
E.id,
E.name,
ARRAY_AGG(DISTINCT R.id) as "regions"
FROM layer_epci E
LEFT JOIN layer_commune C ON C.epci_id = E.id
LEFT JOIN layer_departement D ON C.departement_id= D.id
LEFT JOIN layer_region R ON D.region_id = R.id
GROUP BY E.id
`, {
model: Epci,
mapToModel: true
}).map((row: Epci) => {
// Do some crazy stuff with Epci models.
return epci;
});