Sequelize - 从关联表中返回单列作为自定义列

时间:2016-12-07 08:07:21

标签: mysql sequelize.js

我有两个模型:用户和图像。用户有profile_image_id列。

当我获得include {model:Images, as:'profileImage', attributes:['filename']}的用户时,我将profileImage作为filename作为属性的对象。

Sequelize中是否有办法将'filename'作为User模型的属性? 执行的意义

SELECT u.id, u.name, i.filename 
FROM users u 
LEFT JOIN images i ON i.id = u.profile_image_id 
WHERE u.id = 1

现在有用的是在用户上定义VIRTUAL属性profileImageFIlename,然后在用户模型的afterFind函数中填充它。但这似乎是很多额外的工作和不必要的数据。

除了原始查询之外还有更好的方法吗?

1 个答案:

答案 0 :(得分:4)

简短的回答是,没有办法可以减少工作量。#34;即使在您的示例SQL查询中,您也可以使用为相关i.filename表创建的别名来引用images。这有效地映射到User.images.filename,这与User.profile_image_file一样可用。

如果您希望profile_image_id VIRTUAL作为User上的VIRTUAL字段存在,那么您正在以正确的方式进行操作 - images字段不会被保留到数据库模式,因此您需要从其他来源设置它们。在这种情况下,相关的afterfind()表提供了值,您需要在User挂钩中设置它。

如果您不关心Instance ModelUser.findById(1, { attributes: { include: [[Sequelize.literal('images.filename'), 'profile_image_file']], }, include: [{ model: Images, as: 'images', attributes: [] }] }) .then((user) => { // There will be a user.dataValues.profile_image_file value populated // but not a user.profile_image_file unless you set it in afterFind() console.log(user.dataValues); }); ,并且只想在不必遍历对象的情况下访问结果中的值,可以使用以下内容通过利用Sequelize.literal()来对列进行别名。

SELECT `user`.`id`, `user`.`name`, images.filename AS `profile_image_file`
FROM `user` AS `user` 
LEFT OUTER JOIN `images` AS `images` ON `user`.`profile_image_id` = `images`.`id` 
WHERE `user`.`id` = 1;

这将导致SQL

from caffe import layers as L, params as P
def custom_net(lmdb, batch_size):
    # define your own net!
    n = caffe.NetSpec()

    if lmdb is None: # "deploy" flavor
        # assuming your data is of shape 3x224x224
        n.data = L.Input(input_param={'shape':{'dim':[1,3,224,224]}})
    else:
        # keep this data layer for all networks
        n.data, n.label = L.Data(batch_size=batch_size, backend=P.Data.LMDB, source=lmdb,
                         ntop=2, transform_param=dict(scale=1. / 255))
    # the other layers common to all flavors: train/val/deploy...
    n.conv1 = L.Convolution(n.data, kernel_size=6,
                        num_output=48, weight_filler=dict(type='xavier'))
    n.pool1 = L.Pooling(n.conv1, kernel_size=2, stride=2, pool=P.Pooling.MAX)

    n.conv2 = L.Convolution(n.pool1, kernel_size=5,
                        num_output=48, weight_filler=dict(type='xavier'))
    n.pool2 = L.Pooling(n.conv2, kernel_size=2, stride=2, pool=P.Pooling.MAX)

    n.conv3 = L.Convolution(n.pool2, kernel_size=4,
                        num_output=48, weight_filler=dict(type='xavier'))
    n.pool3 = L.Pooling(n.conv3, kernel_size=2, stride=2, pool=P.Pooling.MAX)

    n.conv4 = L.Convolution(n.pool3, kernel_size=2,
                        num_output=48, weight_filler=dict(type='xavier'))
    n.pool4 = L.Pooling(n.conv4, kernel_size=2, stride=2, pool=P.Pooling.MAX)

    n.fc1 = L.InnerProduct(n.pool4, num_output=50,
                       weight_filler=dict(type='xavier'))
    # do you "drop" i deploy as well? up to you to decide...
    n.drop1 = L.Dropout(n.fc1, dropout_param=dict(dropout_ratio=0.5))
    n.score = L.InnerProduct(n.drop1, num_output=2,
                         weight_filler=dict(type='xavier'))

    if lmdb is None:
        n.prob = L.Softmax(n.score)
    else:
        # keep this loss layer for all networks apart from "Deploy"
        n.loss = L.SoftmaxWithLoss(n.score, n.label)

    return n.to_proto()