.. meta:: :keywords: web2py, framework, DAL, データベース抽象化レイヤ, スマートクエリ .. _smart_query: スマートクエリ ============== スマートクエリは、自然言語を使ってクエリを記述する機能です。まず使用例を示します。 サンプル1 :: >>> s = 'name starts with "S"' >>> print db.smart_query(db.person, s).select() person.id,person.name 2,Socosapo 3,Saduduco personテーブルのnameフィールドで、先頭文字が 'S' のものを取得します。 :ref:`class_dal` クラスのメソッドとして :meth:`~dal.DAL.smart_query` が定義されており、呼び出すと :ref:`class_set` インスタンスを返します。 つまりこのメソッドは、渡したパラメータを、Setインスタンスに変換します。 smart_query メソッドは2つのパラメータを取ります。一つはクエリの対象となるフィールドもしくはテーブルのリスト・タプル型の値(fields)、 もう一つはスマートクエリのクエリ文字列(text)です。これらを詳細に説明します。 fields このパタメータはクエリ式で使用するフィールドを指定します。もしテーブルを指定した場合、テーブルの全フィールドを使用可能になります。 フィールドもしくはテーブルが複数ある場合、リストもしくはタプル型の値で指定します。 text フィールド名と共に演算子を使った、クエリ文字列をパラメータで渡します。演算子として次のキーワードが使用可能です。 .. csv-table:: :header: "演算子","キーワード","","","","","" :widths: 12,14,14,12,12,2,2 論理積(and),and,&,,,, 論理和(or),or,\|,,,, 否定(not),not,~,,,, 等価 [1]_, equal [2]_, equal to [2]_, is [2]_,==,=, 非等価, not equal to [2]_, not equal [2]_, equals [2]_,<>,!=, 小なり, less than [2]_,<,,,, 大なり, greater than ,>,,,, 小なりイコール, less or equal than [2]_, equal or less than [2]_, less or equal [2]_, equal or less [2]_,<=,=< 大なりイコール, greater or equal than [2]_, equal or greater than [2]_, greater or equal [2]_, equal or greater [2]_,=>,>= 前方一致検索, starts with [2]_,startswith,,,, 後方一致検索, ends with [2]_,endswith,,,, 部分一致検索, contains,,,,, あいまい検索, like,,,,, .. [1] textもしくはstringタイプのフィールドに等価を使い、値に定数を使っていない場合、演算子は等価ではなく「あいまい」検索(like)に変換されます。 .. [2] このキーワードでは **is** を先頭に付けることができます。 フィールド名ではなく、Fieldインスタンスを文字列に変換した形式(例 person.name など)も使用可能です。 注意点 * クエリ文字列に記述したものは、全て内部で小文字に変換されます。このような動作に問題がある場合、定数を使用します。 * 定数の指定は、シングルクォーテーション(')もしくはダブルクォーテーション(")で値を囲みます。 * Version 1.99.7以前はバグのため、text及びstring型以外の値を等価で記述するには、定数で指定する必要があります(サンプル5を参照)。 * クエリ文字列で join は表現できないようです。 使用例 ------ 幾つかスマートクエリを使ったサンプルを示します。 サンプル2 :: >>> s = 'name starts with "S"' >>> print db.smart_query(db.person.name, s).select() person.id,person.name 2,Socosapo 3,Saduduco fieldsの指定でTableインスタンスではなく、Fieldインスタンスを指定しています。 Fieldインスタンスを指定した場合は、指定していないフィールドはクエリ文字列で使用することはできません。 サンプル3 :: >>> s = 'name is s%' >>> print db.smart_query(db.person, search).select() person.id,person.name 2,Socosapo 3,Saduduco [1]_ でも説明していますが、textもしくはstringタイプのフィールドに **等価** を使用し、値に **定数** を使っていないと、 内部であいまい検索(like)に変換されます。なおSQLiteを使用する場合、likeでは大文字と小文字を区別しません。 定数を使用する場合は、like演算子を使用します。 :: >>> s = 'person.name like "s%"' >>> print db.smart_query(db.person, s).select() person.id,person.name 2,Socosapo 3,Saduduco サンプル4 :: >>> s = 'name is ends with co' >>> print db.smart_query(db.person, s).select() person.id,person.name 3,Saduduco 一部の演算子キーワードの前に、 **is** キーワードを付けることもできます( [2]_ のキーワード)。 サンプル5 :: >>> s = 'person.id is "2" or person.name is d%' >>> print db.smart_query(db.person, s).select() person.id,person.name 1,Damapoda 2,Socosapo person.id==2 と person.name is d% の論理和で検索します。ここでidを定数で指定しています。これは次のようにも表現できます。 :: s = 'person.id is 2 or person.name is d%' Version 1.99.7 より新しいweb2pyで、使用可能です。 サンプル6 :: >>> s = 'person.name is s% and dog.name is s%' >>> print db.smart_query([db.person,db.dog], s).select(join=db.dog.on(db.person.id==db.dog.owner)) person.id,person.name,dog.id,dog.owner,dog.name 2,Socosapo,2,2,Soducomo スマートクエリでは :ref:`join` は表現できません。このため :meth:`~dal.Set.select` メソッドで join を設定する必要があります。 クエリ文字列に複数のテーブルのフィールドを指定する場合、fieldパラメータに必要なテーブルをリスト型もしくはタプル型で指定してください。 参考: `smart_query (experimental) `_ | `smart_query (実験的) `_ スマートクエリの用途として、サービスへの適用も考えられます。 参考: `smart_query (experimental) service `_ | `smart_query (実験的試み) `_