SequelizeJS-如何为原始查询映射嵌套(紧急加载)模型?

时间:2019-04-05 06:32:34

标签: javascript sequelize.js

下面是原始查询的示例。

  const query = `SELECT 
    links.name, links.type, links.code, links.originalUrl,
    domains.id as 'domain.id', domains.host as 'domain.host',

    count(
      CASE WHEN hits.datetime > "${past}" AND hits.datetime <= "${now}" = true then 1 END
    ) as hitCount 

    FROM links

    LEFT JOIN hits ON links.id = hits.linkId
    LEFT JOIN domains ON links.domainId = domains.id

    WHERE links.userId = ${req.user.id}

    GROUP BY links.id, hits.linkId

    ORDER BY hitCount DESC

    LIMIT 5`;

  const links = await sequelize.query(query.trim(), { 
    type: sequelize.QueryTypes.SELECT,
    model: Link,
    mapToModel: true
  });

我正在使用Link将查询结果映射到模型mapToModel: true中。效果很好,但是当我尝试从连接的表中获取一些数据并将其映射到模型中的对象时,它不会转换为数组。

例如,我正在尝试获取domains.id as 'domain.id', domains.host as 'domain.host',之类的域,这就是我看到对查询急切加载的数据进行序列化的方式。

但是当我得到结果对象时,却没有嵌套的域对象属性。

// desired link object
{
   id: 3,
   name: 'My test link',
   domain: {
      id: 23,
      host: 'example.com'
   }
}

相反,我得到的是

// current link object
{
   id: 3,
   name: 'My test link',
   'domain.id': 23,
   'domain.host': 'example.com'
}

因此嵌套对象无法正确映射。

更新

我找到了nest options in query()文档,但设置nest: true似乎没有任何效果。

更改的查询

  const links = await sequelize.query(query.trim(), { 
    type: sequelize.QueryTypes.SELECT,
    model: Link,
    mapToModel: true,
    nest: true, // doesn't have any effect
  });

5 个答案:

答案 0 :(得分:2)

我遇到了同样的问题。我的解决方案是:

return sequelize.query(/* query */, {
    nest: true,
    type: sequelize.QueryTypes.SELECT
});

如您所见,您不应设置 mapToModel 道具,而应设置嵌套 type

答案 1 :(得分:2)

对我来说nest仅与raw一起工作:

  const links = await sequelize.query(query.trim(), { 
    type: sequelize.QueryTypes.SELECT,
    model: Link,
    mapToModel: true,
    nest: true,
    raw: true // Without this `nest` hasn't effect, IDK why
  });

答案 2 :(得分:0)

据我所知,Link模型具有一个关联的域,因此您需要通过 include: <domain model>映射到域模型。

看看这个:https://github.com/sequelize/sequelize/issues/1830

答案 3 :(得分:0)

您可以自己安装dottie,这就是nest: true应该做的(https://github.com/mickhansen/dottie.js):

import dottie from 'dottie';
// ...
const formattedLinks = links.map(l => dottie.transform(l.toJSON()))

答案 4 :(得分:0)

使用 nest:true 的原始查询似乎不适用于 mapToModel。所以我发现的唯一方法是包含 nest:true,使用 Link.build(link){ include: Domain} 选项映射:

  const query = `SELECT 
    links.name, links.type, links.code, links.originalUrl,
    domains.id as 'domain.id', domains.host as 'domain.host',

    count(
      CASE WHEN hits.datetime > "${past}" AND hits.datetime <= "${now}" = true then 1 END
    ) as hitCount 

    FROM links

    LEFT JOIN hits ON links.id = hits.linkId
    LEFT JOIN domains ON links.domainId = domains.id

    WHERE links.userId = ${req.user.id}

    GROUP BY links.id, hits.linkId

    ORDER BY hitCount DESC

    LIMIT 5`;

  const links = (await sequelize.query(query.trim(), { 
    nest: true,
    type: sequelize.QueryTypes.SELECT,
  }));
  links.map((link) => Link.build(link, {include: Domain}))