使用 Sequelize 仅从行和关联中获取值

Posted

技术标签:

【中文标题】使用 Sequelize 仅从行和关联中获取值【英文标题】:Get only values from rows and associations with Sequelize 【发布时间】:2014-08-17 08:19:54 【问题描述】:

我正在使用 Sequelize、mysql 和 Node 编写一个 Web 应用程序。

对于我的大多数数据库需求,我通常会进行一些验证,然后获取我的模型(热切地使用关联)并将它们发送回客户端,几乎总是按原样(至少到目前为止)。

我写了一个小实用函数getValuesFromRows 来从返回的行数组中提取值:

getValuesFromRows: function(rows, valuesProp) 
    // get POD (plain old data) values
    valuesProp = valuesProp || 'values';
    if (rows instanceof Array) 
        var allValues = [];
        for (var i = 0; i < rows.length; ++i) 
            allValues[i] = rows[i][valuesProp];
        
        return allValues;
    
    else if (rows) 
        // only one object
        return rows[valuesProp];
    
    return null;


// ...

...findAll(...)...complete(function(err, rows) 
     var allValues = getValuesFromRows(rows);
     sendToClient(errToString(err, user), allValues);
);

但是,我正在向我的数据库模型中添加越来越复杂的关系。结果,我得到了更多必须获取的关联。现在,我不仅需要调用上面的函数来从每一行获取values,而且我还需要更复杂的实用程序来从所有包含(急切加载)的关联中获取values。有没有办法只从 Sequelize 查询(而不是 Sequelize 模型实例)中获取值,其中还包括来自实例的所有关联值?

否则,我将不得不手动“从每个Project 中获取所有values,并为Project.members 的每个条目的values 属性向该values 对象添加一项”(例如)。请注意,如果您嵌套关联,事情会变得更糟(例如,成员有 taskstasks 有这个和那个等等)。

我猜我必须自己编写这样的实用程序?

【问题讨论】:

目前.get() 将返回***对象的所有值,但返回包含对象的实例,它正在努力提供一种在调用.get() 时获取普通对象的简单方法(它除非你正在做.get(key)),否则可能是默认设置。作为临时黑客,您可以使用JSON.parse(JSON.stringify(instance)) 获取 POJO。 @MickHansen 1. findAll 返回一个数组。您是说数组添加了get() 方法? 2. 对整个复杂对象进行字符串化将包括各种你不想要的东西。这是不可取的。我会等待并希望有一个更完整的解决方案:) 不,数组只是一个数组,但每个实例都有一个.get()。没有字符串化不会,它使用toJSON 映射到get(),它为您提供基本值。 我不明白。我已经可以通过简单地获取 values 属性来获取 POD 值。为什么使用get() 或 JSON? values 只是映射到get,没有get() 也会为您提供包含的实例,因此它们将具有更多的属性而不仅仅是值(如果您使用了预取)。跨度> 【参考方案1】:

我找到了一个简单的解决我的问题的方法,方法是将上面现有的 POD 转换函数递归到查询的所有 include'd 关联中。该解决方案适用于 findfindAllall 以及可能具有重要结果的其他操作。

代码

/**
 * Get POD (plain old data) values from Sequelize results.
 *
 * @param rows The result object or array from a Sequelize query's `success` or `complete` operation.
 * @param associations The `include` parameter of the Sequelize query.
 */
getValuesFromRows: function(rows, associations) 
    // get POD (plain old data) values
    var values;
    if (rows instanceof Array) 
        // call this method on every element of the given array of rows
        values = [];
        for (var i = 0; i < rows.length; ++i) 
            // recurse
            values[i] = this.getValuesFromRows(rows[i], associations);
        
    
    else if (rows) 
        // only one row
        values = rows.dataValues;

        // get values from associated rows
        if (values && associations) 
            for (var i = 0; i < associations.length; ++i) 
                var association = associations[i];
                var propName = association.as;

                // recurse
                values[propName] = this.getValuesFromRows(values[propName], association.include);
            ;
        
    

    return values;

示例

var postAssociations = [
// poster association

    model: User,
    as: 'author'
,

// comments association

    model: Comment,
    as: 'comments',
    include: [
    
        // author association
        model: User,
        as: 'author'
    
    ]

];

// ...

var query = 
    where: ...
    include: postAssociations;
;

// query post data from DB
return Post.findAll(query)

// convert Sequelize result to POD
.then(function(posts) 
    return getValuesFromRows(posts, postAssociations);
)

// send POD back to client
.then(client.sendPosts);

在上面的例子中,client.sendPosts 接收一个数组。数组的每个条目都将具有属性authorcommentscomments 数组中的每条评论也将有一个 author 属性。整个数组只包含POD(plain old data)。

【讨论】:

以上是关于使用 Sequelize 仅从行和关联中获取值的主要内容,如果未能解决你的问题,请参考以下文章

仅从 sequelize 原始查询而不是模型实例中获取 dataValues

谷歌表格:过滤器/查询/其他从行和列中省略“0”值

Sequelize 从 belongsTo 关系中获取值

Sequelize - 如何从一个表中获取未被另一表关联的条目

Sequelize models - 在 Node 中同步时设置关联

如何在关联表Sequelize js中获取自定义字段