Исключить результаты поиска лития

Я хотел бы исключить результаты вызова метода find() модели Lithium. Мне нужно сделать это для моделей с источниками данных как MongoDB, так и MySQL, но в SQL я имею в виду что-то вроде WHERE myfield NOT IN (1,2,3).

Я хотел бы просто передать предложение not в массиве conditions, как показано ниже, но это не представляется возможным.

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

Итак, мой вопрос: возможно ли это в литии таким образом, который я упустил из виду? А если нет, то какой самый литий-подобный способ реализовать это для моих моделей?


person michaeltwofish    schedule 16.02.2011    source источник


Ответы (2)


Простая фильтрация для 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 );                                                                                                                                                   
    }                                                                                                                                                                                                          
}

(Код может быть немного неверным, так как он в основном взят из моей головы)

person Nervetattoo    schedule 16.02.2011
comment
Спасибо за очень подробный ответ, очень признателен. Отлично работает для MongoDB, но я изо всех сил пытаюсь понять, как переписать условия для MySQL. - person michaeltwofish; 18.02.2011
comment
А, оператор != работает для MySQL. Итак, Item::all(array('conditions' =› array('myfield' =› array('!=', array(1,2,3))))); - person michaeltwofish; 18.02.2011

Чтобы уточнить, адаптер Lithium MongoDB для удобства поддерживает большинство операторов сравнения SQL, поэтому для Mongo или 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] }})
person Nate Abele    schedule 18.02.2011