4

我想排除调用锂模型find()方法的结果。我需要为具有 MongoDB 和 MySQL 数据源的模型执行此操作,但在 SQL 中我的意思是WHERE myfield NOT IN (1,2,3).

我希望能够像下面这样not在数组中传递一个子句conditions,但这似乎是不可能的。

Item::all(array('conditions' => array('not' => array('myfield' => array(1,2,3))));

所以我的问题是,这是否可能以我忽略的方式在锂中实现?如果没有,为我的模型实现它的最锂化的方式是什么?

4

2 回答 2

12

澄清一下,为了方便起见,Lithium 的 MongoDB 适配器支持大多数 SQL 比较运算符,因此对于 MongoMySQL,您可以简单地编写如下查询:

Item::all(array('conditions' => array(
    'myfield' => array('!=' => array(1,2,3))                                                                                                                                                                                 
)));

它应该会给你你期望的结果。对于 MySQL,查询应该类似于:

SELECT * FROM items WHERE myfield NOT IN (1, 2, 3);

在蒙戈:

db.items.find({ myfield: { $nin: [1, 2, 3] }})
于 2011-02-18T06:10:58.683 回答
6

仅对 MongoDB 进行过滤就可以像这样轻松实现:

Item::all(array('conditions' =>                                                                                                                                                                                
    array('myfield' => array(                                                                                                                                                                                  
        '$nin' => array(1,2,3)                                                                                                                                                                                 
    ))                                                                                                                                                                                                         
));                                                                                                                                                                                                            

如果这是你经常做的事情,你甚至可以为它创建一个自定义查找器:

class MyModel extends \lithium\data\Model {                                                                                                                                                                    
    public static function __init()                                                                                                                                                                            
    {                                                                                                                                                                                                          
        parent::__init();                                                                                                                                                                                      

        static::finder('notin', function($self, $params, $chain) {                                                                                                                                             
            // Take all array keys that are not option keys
            $array = array_diff_key($params['options'],
                array_fill_keys(array('conditions', 'fields','order','limit','page'),0));
            // Clean up options leaving only what li3 expects
            $params['options'] = array_diff_key($params['options'], $array);
            $params['options']['conditions'] = array(
                'myfield' => array(
                    '$nin' => $array
                )
            );

            return $chain->next($self, $params, $chain);                                                                                                                                                       
        });                                                                                                                                                                                                    
    }                                                                                                                                                                                                          
}                                                                                                                                                                                                              

并这样称呼它:

MyModel::notin(array(1,2,3));                                                                                                                                                                                  

以同样的方式,您可以为 MySQL 源创建自定义查找器。

正如您可能看到的那样,如果您传递类似的内容,这会产生一些问题,array('fields'=>$array)因为它会覆盖选项。发生的情况是::notin()(通常的查找器)对 (array,null) 签名具有不同的行为。如果发生这种情况,它认为第一个数组是选项并且查找器不接受任何参数。Usingnotin($array,array())会破坏前一个查找器,因为第一个参数在$params['notin']传递真正的第二个参数(选项)时结束。

如果您在这里动态混合数据源,我将创建一个不继承 \lithium\data\Model 的自定义模型,并将其委托
给不同的模型并根据最终模型数据源创建条件。

class MyFacadeModel {                                                                                                                                                                                          
    public static function byNotIn($conditions, $source) {                                                                                                                                                     
        return ($source == "mongodb")                                                                                                                                                                          
            ? $source::find( $rewrittenConditions)                                                                                                                                                             
            : $source::find( $rewrittenConditionsForMysql );                                                                                                                                                   
    }                                                                                                                                                                                                          
}

(代码可能有点不正确,因为它主要取自我的头顶)

于 2011-02-16T12:34:30.920 回答