4

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

だから私の質問は、これは私が見落としていた方法でリチウムで可能ですか? そうでない場合、私のモデルにそれを実装する最もリチウムっぽい方法は何でしょうか?

4

2 に答える 2

12

明確にするために、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] }})
于 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) 署名に対して異なる動作をします。その場合、最初の配列はオプションであり、ファインダは引数を取りませんでした。実際の 2 番目の引数 (オプション) が渡されたときに最初の引数が終了するため、使用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 );                                                                                                                                                   
    }                                                                                                                                                                                                          
}

(コードはほとんど頭のてっぺんから取ったものなので、少し間違っているかもしれません)

于 2011-02-16T12:34:30.920 に答える