自定义数据检索/查找器

时间:2014-02-06 15:24:54

标签: sequelize.js

我想在我的sequelize对象上定义一个自定义查找程序。例如,假设我有一个订单模型。

var Orders = sequelize.define('Orders', {
  ...
})

我有一个复杂的查询,我想在不同的地方重用。

var sql = 'SELECT'
  + ' CONCAT_WS(\':\', `type`, `id`) AS `id`'
  + ' , `type`'
  + ' , `name`'
  + ' , `amount`'
  + ' , `quantity`'
  + ' , `total`'
  + ' , `createdAt`'
  + ' FROM (' 
  + ' SELECT'
  + '  OrderItems.id AS `id`'
  + ' , \'item\' AS `type`'
  + ' , Items.name AS `name`'
  + ' , Items.price AS `amount`'
  + ' , OrderItems.quantity AS `quantity`'
  + ' , OrderItems.quantity * Items.price AS `total`'
  + ' , OrderItems.createdAt AS `createdAt`'
  + ' FROM OrderItems'
  + ' INNER JOIN Items ON Items.id = OrderItems.ItemId'
  + ' WHERE OrderId = :OrderId'
  + ' UNION'
  + ' SELECT'
  + '  OrderPayments.id AS `id`'
  + ' , \'payment\' AS `type`'
  + ' , Payments.name AS `name`'
  + ' , OrderPayments.amount AS `amount`'
  + ' , 0 AS `quantity`'
  + ' , OrderPayments.amount AS `total`'
  + ' , OrderPayments.createdAt AS `createdAt`'
  + ' FROM OrderPayments'
  + ' INNER JOIN Payments ON Payments.id = OrderPayments.PaymentId'
  + ' WHERE OrderId = :OrderId'
  + ' ) OrderLines'
  + ' ORDER BY createdAt DESC'

以下是我要运行查询的方法。

Orders.find(123).success(function(order) {
    order.getDataFromMyComplexQuery('arg1', 'arg2').success(function(results){
        // Do something with the results
    })
});

或者喜欢:

Orders.getDataFromMyComplexQuery('arg1', 'arg2').success(function(results){
    // Do something with the results
})

这就像存储过程,但在Sequelize中。

2 个答案:

答案 0 :(得分:0)

好吧,在这里我们似乎陷入了由不同的JavaScript开发人员提供的术语混乱。 Sequelize中称为模型的东西看起来像Repository。但模型 - 是Repository中定义的参数。确切地说,在任何finder方法上返回的模型(或模型集合)。 清除这些内容使得易于理解您的任务是使用自定义查找程序扩展存储库。 我是这样做的:

/**
     * custom method to retrieve matches by complex conditions
     * @param roundId – integer, required
     * @param conditions – optional object of type: { teamId: integer, isFinished: boolean, searchTerm: string }
     * to catch result chain .success( function( matches ){} ) call
     * to catch error chain .error( function( errorText ){} ) call
     * @return this to make chaining available
     */
    matchesRepository.getByRound = function( roundId, conditions ){
        /** handling chaining for .success and .error callbacks */
        var successCallback,
            errorCallback
            self = this;
        this.success = function( callback ){
            if( 'function' != typeof callback ){
                throw "Function expected as successCallback"
            }
            successCallback = callback;
            return self;
        }
        this.error = function( callback ){
            if( 'function' != typeof callback ){
                throw "Function expected as callback";
            }
            errorCallback = callback;
            return self;
        }

        /** validate params */
        var roundId = parseInt( roundId );
        if( isNaN( roundId ) ){
            errorCallback( "Unable to getByRound matches until roundId not specified" );
            return this;
        }

        if( 'undefined' == typeof conditions ){
            conditions = {};
        }

        /** build statement */
        var statement = "SELECT @matches.* FROM @matches " +
                        "LEFT OUTER JOIN @teams as team1 ON team1.team_id = @matches.id_team1 " +
                        "LEFT OUTER JOIN @teams as team2 ON team2.team_id = @matches.id_team2 WHERE ";
        var where = [];

        if( 'undefined' != typeof conditions.teamId ){
            var teamId = parseInt( conditions.teamId );
            if( isNaN( teamId ) ){
                errorCallback( "Integer or eval string expected in conditions.teamId; `" +
                                conditions.teamId + "` provided" );
                return this;
            }
            where.push( '( (id_team1 = ' + teamId + ' OR id_team2 = ' + teamId + ') )' );
        }
        if( 'undefined' != typeof conditions.isFinished ){
            if( true == conditions.isFinished ){
                where.push( '( gf IS NOT NULL AND ga IS NOT NULL )' );
            } else {
                where.push( '( gf IS NULL AND ga IS NULL )' );
            }
        }
        if( 'undefined' != typeof conditions.searchTerm ){
            where.push( '( team1.title LIKE "%' + conditions.searchTerm + '%" OR ' +
                        'team2.title LIKE "%' + conditions.searchTerm + '%" )' );
        }
        var matchesTable = core.factories.match.name,
            teamsTable = core.factories.team.name,
            preparedQuery = statement + where.join( " AND " ),
            sqlQuery = preparedQuery.replace( /@matches/g, matchesTable )
                                    .replace( /@teams/g, teamsTable );

        sequelize.query( sqlQuery )
            .success( function( matches ){
                successCallback( matches );
            })
            .error( function( errorText ){
                errorCallback( errorText );
            });
        return this;
    }

答案 1 :(得分:0)

您可以使用instanceMethods和classMethods对象定义自定义方法。来自docs

  

Sequelize允许您将自定义方法传递给模型   实例。只需执行以下操作:

var Foo = sequelize.define('Foo', { /* attributes */}, {
  classMethods: {
    method1: function(){ return 'smth' }
  },
  instanceMethods: {
    method2: function() { return 'foo' }
  }
})

// Example:
Foo.method1()
Foo.build().method2()