我正在努力使用 sequelize 创建查询。
一些上下文
我有以下型号:
Manifestation
可以有 [0..n] Event
Event
属于一个 Manifestation
(没有 Event
就不能存在 Manifestation
) Place
可以有 [0..n] Event
Event
属于一个 Place
(没有 Event
就不能存在 Place
) Manifestation
可以有 [1..n] Place
Place
可以有 [0..n] Manifestation
我将关系建模如下:
Manifestation.hasMany(Event, { onDelete: 'CASCADE', hooks: true })
Event.belongsTo(Manifestation)
Place.hasMany(Event, { onDelete: 'CASCADE', hooks: true })
Event.belongsTo(Place)
Manifestation.belongsToMany(Place, { through: 'manifestation_place' })
Place.belongsToMany(Manifestation, { through: 'manifestation_place' })
对我来说,这似乎相当正确,但如果您有意见,请不要犹豫。
问题
我正在尝试查询
Place
为了得到所有Manifestation
和 Event
发生在给定的 Place
.但是对于Event
的,我想将它们包含在他们的 Manifestation
中即使Manifestation
在给定的 Place
中不会发生.下面是我试图实现的“JSON”结构:
{
id: 1,
name: "Place Name",
address: "Place address",
latitude: 47.00000,
longitude: -1.540000,
manifestations: [
{
id: 10,
title: "Manifestation one",
placeId: 1,
events: []
},
{
id: 11,
title: "Manifestation two",
placeId: 3,
events: [
id: 5,
title: "3333",
manifestationId: 11,
placeId: 1
]
}
]
}
所以我想包括
Manifestation
与 id
: 11, 因为它的一个 Event
发生在给定的 Place
(与 id
:1)更新 (04/06/20):现在我依靠 javascript 来获得预期的结果
我想如果我在询问之前发布我当前的解决方案会很好。
router.get('/test', async (req, res) => {
try {
const placesPromise = place.findAll()
const manifestationsPromise = manifestation.findAll({
include: [
{ model: event },
{
model: place,
attributes: ['id'],
},
],
})
const [places, untransformedManifestations] = await Promise.all([
placesPromise,
manifestationsPromise,
])
const manifestations = untransformedManifestations.map(m => {
const values = m.toJSON()
const places = values.places.map(p => p.id)
return { ...values, places }
})
const result = places
.map(p => {
const values = p.toJSON()
const relatedManifestations = manifestations
.filter(m => {
const eventsPlaceId = m.events.map(e => e.placeId)
return (
m.places.includes(values.id) ||
eventsPlaceId.includes(values.id)
)
})
.map(m => {
const filteredEvents = m.events.filter(
e => e.placeId === values.id
)
return { ...m, events: filteredEvents }
})
return { ...values, manifestations: relatedManifestations }
})
.filter(p => p.manifestations.length)
return res.status(200).json(result)
} catch (err) {
console.log(err)
return res.status(500).send()
}
})
但我很确定我可以直接用 sequelize 做到这一点。任何想法或建议?
谢谢
最佳答案
这不是最佳的。但是你可以试试:
const findPlace = (id) => {
return new Promise(resolve => {
db.Place.findOne({
where: {
id: id
}
}).then(place => {
db.Manefestation.findAll({
include: [{
model: db.Event,
where: {
placeId: id
}
}]
}).then(manifestations => {
const out = Object.assign({}, {
id: place.id,
name: place.name,
address: place.address,
latitude: place.latitude,
longitude: place.longitude,
manifestations: manifestations.reduce((res, manifestation) => {
if (manifestation.placeId === place.id || manifestation.Event.length > 0) {
res.push({
id: manifestation.id,
title: manifestation.id,
placeId: manifestation.placeId,
events: manifestation.Event
})
}
return res;
}, [])
})
})
resolve(out);
})
})
}
从中,您将获得分配给地点或具有任何分配事件的所有表现形式。所有包含在 manefestations 中的事件都被分配到这个地方。
编辑:
您也可以使用以下方法:
const findPlace = (id) => {
return new Promise(resolve => {
db.Place.findOne({
include: [{
model: db.Manefestation,
include: [{
model: db.Event,
where: {
placeId: id
}
}]
}],
where: {
id: id
}
}).then(place => {
db.Manefestation.findAll({
include: [{
model: db.Event,
where: {
placeId: id
}
}],
where: {
placeId: {
$not: id
}
}
}).then(manifestations => {
place.Manefestation = place.Manefestation.concat(manifestations.filter(m=>m.Event.length>0))
resolve(place);// or you can rename, reassign keys here
})
})
})
}
这里我只取第一个查询中的直接表现。然后,不包括和连接的表现形式。
关于sql - 在包含的包含上使用 where 子句对查询进行 Sequelize,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60863743/