2011-02-16 5 views
4

리튬 모델의 find() 메서드 호출 결과를 제외하고 싶습니다. MongoDB와 MySQL 데이터 소스가있는 모델에서는이 작업을 수행해야하지만, SQL에서는 WHERE myfield NOT IN (1,2,3)과 같은 것을 의미합니다.Lithium에서 결과 제외

아래와 같이 절을 conditions 배열에 전달할 수는 있지만 가능한 것은 아닙니다.

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

제 질문은 간과 한 방식으로 리튬에서 가능합니까? 그리고 그렇지 않다면, 내 모델을 위해 그것을 구현하는 가장 리튬적인 방법은 무엇이겠습니까?

단순히 MongoDB를 필터링

답변

6

쉽게 다음과 같이 얻을 수있다 :

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() (일반적으로 찾기)은 (배열, null) 서명에 대해 고유 한 동작을합니다. 그럴 경우 첫 번째 배열이 옵션이고 파인더가 인수를 취하지 않는다고 생각합니다. 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

감사합니다, 많은 감사 MySQL의 경우, 쿼리는 같은 것을 보일 것입니다. MongoDB를 완벽하게 지원하지만 MySQL의 조건을 다시 작성하는 방법을 고민하고 있습니다. – michaeltwofish

+0

아,! = 연산자는 MySQL에서 작동합니다. 그래서 항목 :: 모든 (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))                                             
))); 

을 그리고 그것은 당신에게 당신이 기대하는 결과를 제공한다.

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

그리고 몽고에서 : 매우 상세한 답변을

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