简体   繁体   English

排除来自Lithium find的结果

[英]Exclude results from Lithium find

I'd like to exclude results from a call to a Lithium model's find() method. 我想从调用Lithium模型的find()方法中排除结果。 I need to do this for models with both MongoDB and MySQL data sources, but in SQL I mean something like WHERE myfield NOT IN (1,2,3) . 我需要为包含MongoDB和MySQL数据源的模型执行此操作,但在SQL中我的意思是像WHERE myfield NOT IN (1,2,3)

I'd like to just be able to pass a not clause in the conditions array like below, but that doesn't appear to be possible. 我想能够在conditions数组中传递一个not子句,如下所示,但这似乎不可能。

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

So my question is, is this possible in Lithium in a way that I've overlooked? 所以我的问题是,这是否有可能在锂中以我忽略的方式? And if not, what would be the most Lithium-ish way to implement it for my models? 如果没有,那么为我的模型实施它的最简单方法是什么?

Just to clarify, Lithium's MongoDB adapter supports most SQL comparison operators as a convenience, so for either Mongo or MySQL, you could simply write the query as follows: 为了澄清一下,Lithium的MongoDB适配器支持大多数SQL比较运算符,因此对于Mongo MySQL,您只需按如下方式编写查询:

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

And it should give you the results you expect. 它应该给你你期望的结果。 For MySQL, the query should look something like: 对于MySQL,查询应该类似于:

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

And in Mongo: 在Mongo:

db.items.find({ myfield: { $nin: [1, 2, 3] }})

Merely filtering for MongoDB can easily be achieved like this: 只需过滤MongoDB即可轻松实现:

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

If this is something you do a lot you could even create a custom finder for it : 如果这是你做了很多事情,你甚至可以为它创建一个自定义查找程序:

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);                                                                                                                                                       
        });                                                                                                                                                                                                    
    }                                                                                                                                                                                                          
}                                                                                                                                                                                                              

And call it like this : 并称之为:

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

In the same manner you could create a custom finder for MySQL sources. 以同样的方式,您可以为MySQL源创建自定义查找程序。

As you probably can see this creates some issues if you pass something like array('fields'=>$array) as it would overwrite the option. 正如您可能会看到的那样,如果您传递类似array('fields'=>$array)内容会产生一些问题,因为它会覆盖该选项。 What happens is that ::notin() (finders in general) has a distinct behavior for the (array,null) signature. 会发生什么::notin() (一般的::notin()对(array,null)签名有不同的行为。 If that happens it thinks the first array is options and the finder took no arguments. 如果发生这种情况,它认为第一个数组是选项而finder没有参数。 Using notin($array,array()) breaks the previous finder because the first argument ends up in $params['notin'] when the real second argument (options) is passed. 使用notin($array,array())会破坏前一个查找器,因为第一个参数在传递真正的第二个参数(选项)时以$params['notin']结束。

If you mix data sources on the fly here I would create a custom model that does not inherit \\lithium\\data\\Model and have it delegate 如果您在这里动态混合数据源,我会创建一个不继承\\ lithium \\ data \\ Model并让它委托的自定义模型
to the different models and create the conditions based on the end models data source. 根据不同的模型创建基于最终模型数据源的条件。

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

(Code might be slightly incorrect as its mostly taken from the top of my head) (代码可能稍微不正确,因为它主要取自我的头脑)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM