问题
I want to fetch data from a Postgres database recursively including all associated models using SequelizeJS.
GeoLocations table
id | isoCode | name | parentId | type | updatedAt | deletedAt
parentId holds the id of the parent GeoLocation.
Model Associations
GeoLocation.belongsTo(GeoLocation, {
foreignKey: 'parentId',
as: 'GeoLocation'
});
Data explanation and example
GeoLocation types and their relations:
city -> subdivision -> country -> continent
id: 552, name: Brooklyn, type: city, parentId: 551
id: 551, name: New York, type: subdivision, parentId: 28
id: 28, name: United States, type: country, parentId: 27
id: 27, name: North America, type: continent, parentId: NULL
Now, when querying a city, I want all relations to be included as long as parentId is set.
GeoLocation.findOne({
where: {
id: 552
},
include: [
{
model: GeoLocation,
as: 'GeoLocation',
include: [
{
model: GeoLocation,
as: 'GeoLocation',
include: [
{
model: GeoLocation,
as: 'GeoLocation',
}
],
}
],
}
],
});
Response in JSON
{
"GeoLocation":{
"id":552,
"type":"city",
"name":"Brooklyn",
"GeoLocation":{
"id":551,
"type":"subdivision",
"name":"New York",
"GeoLocation":{
"id":28,
"type":"country",
"name":"United States",
"GeoLocation":{
"id":27,
"type":"continent",
"name":"North America"
}
}
}
}
}
The solution above works, but I have the strong feeling, that there are better ways to do this, without having to include the model multiple times. I can't find anything related in the docs. Am I missing something?
回答1:
I already moved on a different solution. I am not using sequelize native pseudo language to achieve this. Because apparently, recursive includes feature is not possible with sequelize.
Here is the recursive model I use :
I want this recursive info, which organisation is related to which, no matter how I get this info, I'll process it later to get the info into shape (tree, flat list, ... whatever)
I use a sequelize RAW query involving recursive SQL:
exports.getArborescenceByLienId = function (relationType, id) {
const query = 'With cte as (\n' +
' select id_organisationSource, \n' +
' relationType,\n' +
' id_organisationTarget\n' +
' from (\n' +
' select * from relation where relationType= :relationType\n' +
' ) relations_sorted,\n' +
' (\n' +
' select @pv := :orgId\n' +
' ) initialisation\n' +
' where find_in_set(id_organisationSource, @pv)\n' +
' and length(@pv := concat(@pv, \',\', id_organisationTarget))\n' +
')\n' +
'select source.id as `idSource`, cte.relationType, target.id as `idTarget`\n' +
'from cte \n' +
'left outer join organisation source on cte.id_organisationSource = source.id\n' +
'left outer join organisation target on cte.id_organisationTarget = target.id;';
return models.sequelize.query(
query,
{
type: models.sequelize.QueryTypes.SELECT,
replacements: { orgId: id, relationType: relationType}
}
);
};
Imagine I have an object model like this:
(Assuming each relation here have same type : say isManaging) Result of query with ID = 1 would be :
Result of query with ID = 2 would be :
I then transform this flat list to a Tree, and VOILA :)
Let me know if your interested in this Flat list to tree transforming algorithm.
Hope this help. Cheers !
来源:https://stackoverflow.com/questions/44456470/sequelizejs-recursive-include-same-model