2011-02-16 62 views
4

我想排除鋰電池模型find()方法調用的結果。我需要爲具有MongoDB和MySQL數據源的模型執行此操作,但在SQL中,我的意思是WHERE myfield NOT IN (1,2,3)排除鋰電池的結果find

我想只能通過conditions數組中的not子句,如下所示,但這似乎不可能。

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

所以我的問題是,這是否可能在鋰的方式,我忽略了?如果不是的話,那麼對我的模型實施它的最鋰鋰電方式是什麼?

回答

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()(一般發現者)對於(數組,空)簽名具有不同的行爲。如果發生這種情況,它認爲第一個數組是選項,查找器沒有任何參數。 使用notin($array,array())打破了以前的查找器,因爲第一個參數結束於$params['notin'],當真正的第二個參數(選項)通過。

如果您在此處混合使用數據源,我會創建一個不會繼承\ lithium \ data \ Model的自定義模型,並將其委託給不同的模型,並根據最終模型數據源創建條件。

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

(其主要是從我的頭頂取代碼可能會稍有不正確的)

+0

感謝非常詳細的解答,不勝感激。適用於MongoDB,但我正努力研究如何重寫MySQL的條件。 – michaeltwofish

+0

啊,!=運算符適用於MySQL。所以Item :: all(array('conditions'=> array('myfield'=> array('!=',array(1,2,3))))); – michaeltwofish

12

只是爲了澄清,鋰的MongoDB的適配器支持大多數SQL比較操作的方便,所以無論是蒙戈 MySQL,你可以簡單地編寫查詢如下:

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