2.14. スマートクエリ

スマートクエリは、自然言語を使ってクエリを記述する機能です。まず使用例を示します。

サンプル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’ のものを取得します。

DAL クラスのメソッドとして smart_query() が定義されており、呼び出すと Set インスタンスを返します。 つまりこのメソッドは、渡したパラメータを、Setインスタンスに変換します。

smart_query メソッドは2つのパラメータを取ります。一つはクエリの対象となるフィールドもしくはテーブルのリスト・タプル型の値(fields)、 もう一つはスマートクエリのクエリ文字列(text)です。これらを詳細に説明します。

fields
このパタメータはクエリ式で使用するフィールドを指定します。もしテーブルを指定した場合、テーブルの全フィールドを使用可能になります。 フィールドもしくはテーブルが複数ある場合、リストもしくはタプル型の値で指定します。
text

フィールド名と共に演算子を使った、クエリ文字列をパラメータで渡します。演算子として次のキーワードが使用可能です。

演算子 キーワード          
論理積(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](1, 2) textもしくはstringタイプのフィールドに等価を使い、値に定数を使っていない場合、演算子は等価ではなく「あいまい」検索(like)に変換されます。
[2](1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18) このキーワードでは is を先頭に付けることができます。

フィールド名ではなく、Fieldインスタンスを文字列に変換した形式(例 person.name など)も使用可能です。

注意点

  • クエリ文字列に記述したものは、全て内部で小文字に変換されます。このような動作に問題がある場合、定数を使用します。
  • 定数の指定は、シングルクォーテーション(’)もしくはダブルクォーテーション(”)で値を囲みます。
  • Version 1.99.7以前はバグのため、text及びstring型以外の値を等価で記述するには、定数で指定する必要があります(サンプル5を参照)。
  • クエリ文字列で join は表現できないようです。

2.14.1. 使用例

幾つかスマートクエリを使ったサンプルを示します。

サンプル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

スマートクエリでは テーブル結合(join) は表現できません。このため select() メソッドで join を設定する必要があります。 クエリ文字列に複数のテーブルのフィールドを指定する場合、fieldパラメータに必要なテーブルをリスト型もしくはタプル型で指定してください。

参考: smart_query (experimental)smart_query (実験的)

スマートクエリの用途として、サービスへの適用も考えられます。

参考: smart_query (experimental) servicesmart_query (実験的試み)