SequelizeJS:递归包含相同的模型

时间:2017-06-09 11:18:45

标签: postgresql recursion sequelize.js

我希望使用SequelizeJS递归地从Postgres数据库中获取数据,包括所有相关模型。

地理位置表

id | isoCode | name | parentId | type | updatedAt | deletedAt

parentId保存父GeoLocation的ID。

模型关联

GeoLocation.belongsTo(GeoLocation, {
    foreignKey: 'parentId',
    as: 'GeoLocation'
});

数据说明和示例

GeoLocation类型及其关系: 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

现在,在查询城市时,我希望只要设置parentId就可以包含所有关系。

GeoLocation.findOne({
    where: {
        id: 552
    },
    include: [
        {
            model: GeoLocation,
            as: 'GeoLocation',
            include: [
                {
                    model: GeoLocation,
                    as: 'GeoLocation',
                    include: [
                        {
                            model: GeoLocation,
                            as: 'GeoLocation',
                        }
                    ],
                }
            ],
        }
    ],
});

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"
            }
         }
      }
   }
}

上面的解决方案有效,但我有强烈的感觉,有更好的方法来做到这一点,而不必多次包含模型。我在文档中找不到任何相关内容。我错过了什么吗?

1 个答案:

答案 0 :(得分:0)

我已经采用了不同的解决方案。我没有使用sequelize本地伪语言来实现这一点。因为显然,所以sequelize不能使用递归包含功能。

这是我使用的递归模型: Recursive model

我想要这个递归信息,哪个组织与哪个组织相关,无论我如何得到这些信息,我都会稍后处理它以使信息变成形状(树,平面列表,......等等)

我使用了一个涉及递归SQL的sequelize RAW查询:

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

想象一下,我有一个像这样的对象模型:

Recursive object model (假设这里的每个关系都有相同的类型:说isManaging) ID = 1的查询结果为: Query result ID1

ID = 2的查询结果将是: Query result ID2

然后我将这个平面列表转换为树,并且VOILA:)

如果您对此平面列表感兴趣,请使用树转换算法。

希望这有帮助。干杯!