REST API
下の最初の形式は、等価条件です。つまり、プロパティ が 値 と等しいかどうかをテストします。 下の2番目のフォームは、他のすべての条件です。
filter[where][property]=value
filter[where][property][op]=value
例えば、odo
プロパティを持つ自動車(car)モデルがあったとして、以下の検索では odo
が5000より大きいインスタンスを抽出します。
/cars?filter[where][odo][gt]=5000
例えば、これは odo
が30,000よりも小さい自動車を検索します。
/cars?filter[where][odo][lt]=30000
REST検索では、文字列化したJSON形式を使うこともできます。
フィルタの制限
Important:
qs を使用するため、この形式の使用には(ANDまたはORと組み合わせて)20個のフィルタまでの制限があります。20を超えるフィルタがある場合、フィルタは Arary
が期待される場所で、Object
に変換されるためエラーになります。詳細についてはLoopBack issue #2824を参照してください。
フィルタの制限を回避する方法は2つあります。
- 大きなフィルタオブジェクトを、「文字列化したJSON」に変換する。
server/server.js
でboot()
が呼び出される前に、制限値を変更する。
フィルタオブジェクトをJSONに変換する
http://localhost:3000/api/Books
?filter={"where":{"or":[{"id":1},{"id":2},...,{"id":20"},{"id":21}]}}
server.js
で制限値を上書きする
// In `server/server.js`, before boot is called
var loopback = require('loopback');
var boot = require('loopback-boot');
var qs = require('qs');
var app = module.exports = loopback();
app.set('query parser', function(value, option) {
return qs.parse(value, {arrayLimit: 500});
});
app.start = function() {
...
Node API
検索のwhere句
find()
・findOrCreate()
・findOne()
などの検索メソッドでは、等価性( プロパティ が 値 と等しいこと)のテストに下の最初の形式を使ってください。
その他全ての条件については、下の2つ目の形式を使ってください。
{where: {property: value}}
{where: {property: {op: value}}}
ここで、
- property は、検索されるモデル内のプロパティ(フィールド)の名前です。
- value はリテラル値です。
- op は以下に挙げる演算子のいずれかになります。
Cars.find({where: {carClass:'fullsize'}});
等価な REST 検索は以下のようになります。
/api/cars?filter[where][carClass]=fullsize
Tip: 上記のwhere句構文は検索用であり、count()
用ではありません。
count()
を含む、その他全てのメソッドでは、{ where : ... }
の囲みを外してください。以下の他のメソッドでのwhere句を参照してください。
他のメソッドでのwhere句
Important:
検索以外のメソッド つまり、更新や削除のメソッド(そしてcount()
)のNode APIを呼び出すときは、where句を { where : ... }
オブジェクトで囲まないで、以下に示すように単に引数として指定するようにしてください。以下の例を参照してください。
下の最初の形式は、等価条件です。つまり、プロパティ が 値 と等しいかどうかをテストします。下の2番目のフォームは、他のすべての条件です。
{property: value}
{property: {op: value}}
ここで、
- property は、検索されるモデル内のプロパティ(フィールド)の名前です。
- value はリテラル値です。
- op は以下に挙げる演算子のいずれかになります。
例えば、以下に示すのが、モデルのupdateAll()メソッドの呼出しにおけるwhere句です。
引数では{ where : ... }
がないことに注意してください。
var myModel = req.app.models.Thing;
var theId = 12;
myModel.updateAll( {id: theId}, {regionId: null}, function(err, results) {
return callback(err, results);
});
他の例として、今度は destroyAll() を呼び出す場合です。
var RoleMapping = app.models.RoleMapping;
RoleMapping.destroyAll( { principalId: userId }, function(err, obj) { ... } );
cost プロパティが100より大きいレコードを削除するには、以下のようになります。
productModel.destroyAll({cost: {gt: 100}}, function(err, obj) { ... });
whereフィルタの既定スコープ
(model.json
ファイル内の)モデル定義に scope
を追加すると、
自動的に defaultScope()
メソッドが追加されます。LoopBack はモデルが作成・更新・検索される時はいつでもこのメソッドを呼出します。
Tip: where
フィルタを使用したデフォルトスコープは、期待どおりに機能しない可能性があります。
モデルインスタンスが生成されたり更新されたりする都度、生成された defaultScope()
メソッドは where
フィルタに一致するモデルのプロパティを変更して、指定された値を適用します。
このようにデフォルトスコープを適用したくない場合は、可能であれば名前付きスコープを使用してください。
デフォルトのスコープを使用する必要があるが、そのスコープに影響されたくない場合、upsert()
などは、たとえば、 upsert()
の呼び出し前にモデルのdefaultScope()
メソッドをオーバーライドするだけです。
例えば以下のようにします。
var defaultScope = Report.defaultScope;
Report.defaultScope = function(){};
Report.upsert({id: reportId, 'deleted': true}, function(...) {
Report.defaultScope = defaultScope;
...
});
演算子
この表では、「where」フィルタで使用できる演算子について説明します。 以下の例を参照してください。
演算子 | 説明 |
---|---|
= | 等価性。 以下の例 参照。 |
and | 論理 AND 演算子。 下のANDとOR演算子と例を参照。 |
or | 論理 OR 演算子。 下のANDとOR演算子と例を参照。 |
gt, gte | 数値がより大きい (>)、以上 (>=)。数値と日付にのみ使用できます。下の例 を参照。 位置情報の値は、既定ではマイル単位です。詳細は、 Geopointを参照してください。 |
lt, lte | 数値がより小さい (<)、以下 (<=)。数値と日付にのみ使用できます。 位置情報の値は、既定ではマイル単位です。詳細は、 Geopointを参照してください。 |
between | 値が、2つの指定された値の間にある(1つ目の値以上かつ、2つ目の値以下)場合は true。下の例を参照。 位置情報の値は、既定ではマイル単位です。 詳細は、 Geopointを参照してください。 |
inq, nin | 値の配列に含まれる/含まれない。下の例を参照。 |
near | 位置情報において、距離でソートしたときに最も近い点を返す。limit を使って、最も近い n 個の点を返すことができる。下の 例 を参照。 |
neq | 等しくない (!=) |
like, nlike | 正規表現を使用する LIKE / NOT LIKE 演算子。正規表現の形式は、バックエンドのデータソースに依存します。下の例 を参照。 |
like, nlike, オプション:i | 大文字・小文字を無視するフラグのついた、正規表現を使用する LIKE / NOT LIKE 演算子。memory と MongoDB コネクタで使用可能。options プロパティを ‘i’ にセットすることで、LoopBack は 大文字小文字を無視したマッチングを行う。下の例 を参照。 |
ilike, nilike | 正規表現を使用する ILIKE / NOT ILIKE 演算子。memory と Postgresql コネクタでのみ使用可能。下の 例 を参照。 |
regexp | 正規表現。 下の 例 を参照。 |
AND と OR 演算子
AND演算子とOR演算子を使用して、次の構文で、単純なwhereフィルタ条件に基づいて複合論理フィルタを作成します。
{where: {<and|or>: [condition1, condition2, ...]}}
REST
[where][<and|or>][0]condition1&[where][<and|or>]condition2...
ここで、condition1 と condition2 はフィルタ条件です。
下の例を参照してください。
正規表現
whereフィルタでは、次の構文で正規表現を使用できます。where句の正規表現を使用して、検索同様に更新と削除を行うことができます。
基本的に regexp
は、比較値として正規表現の値を与える演算子のようなものです。
Tip: 正規表現の値には、1つ以上のフラグを含めることもできます。たとえば /i
を正規表現に追加して大文字小文字を区別しないマッチを実行します。
{where: {property: {regexp: <expression>}}}
ここで、<expression>
は以下のいずれかを取りえます。
- 正規表現を定義する文字列 (例えば、
'^foo'
)。 - 正規表現リテラル (例えば、
/^foo/
)。 - 正規表現オブジェクト (例えば、
new RegExp(/John/)
)。
より単純な形式も可能です。
{where: {property: <expression>}}}
ここで、<expression>
は以下のいずれかを取りえます。
- 正規表現リテラル (例えば、
/^foo/
)。 - 正規表現オブジェクト (例えば、
new RegExp(/John/)
)。
JavaScriptの正規表現についてより詳細な情報は、 正規表現 (Mozilla Developer Network)を参照してください。
Tip: 上記のwhere句構文は検索用です。 更新および削除の場合は、{ where : … }の囲みを省略します。 以下の他のメソッドでのWhere句を参照してください。
たとえば、この検索は、車種(model)が大文字の “T”で始まるすべての車を返します。
Cars.find( {"where": {"model": {"regexp": "^T"}}} );
または、単純な形式を使うと以下のようになります。
Cars.find( {"where": {"model": /^T/} } );
REST
filter[where][property][regexp]=expression
ここで、
- property は、検索されるモデル内のプロパティ(フィールド)の名前です。
- expression はJavaScriptの正規表現文字列です。正規表現 (Mozilla Developer Network)を参照してください。
正規表現の値は、1つ以上のフラグを含めることができます。
例えば、正規表現に /i
を追加すると、大文字小文字を区別しないマッチを行います。
Important:
REST APIで正規表現のフラグを使用する場合は、
正規表現の前にスラッシュ文字(/
)を 付けなければ なりません。
次のREST検索は、車種(model)が大文字の「T」で始まるすべての自動車(car)を返します。
/api/cars?filter[where][model][regexp]=^T
次のREST検索は、大文字の「T」または小文字の「t」で始まるすべての車種(model)を返します。
/api/cars?filter[where][model][regexp]=/^t/i
正規表現にはフラグが含まれているため、スラッシュ(/
)が前に付いています。
例
等価性
「M1911」という名前の武器:
REST
/weapons?filter[where][name]=M1911
carClassが「fullsize」である自動車:
REST
/api/cars?filter[where][carClass]=fullsize
Nodeで等価な処理:
Cars.find({ where: {carClass:'fullsize'} });
gt と lt
ONE_MONTH = 30 * 24 * 60 * 60 * 1000; // ミリ秒で1ヶ月
transaction.find({
where: {
userId: user.id,
time: {gt: Date.now() - ONE_MONTH}
}
}
例えば、以下の検索は従業員(employee)モデルから、where フィルタを使って、dateプロパティが指定した日時より大きいインスタンスを返します。
/employees?filter[where][date][gt]=2014-04-01T18:30:00.000Z
Node APIで同じ検索を行います。
Employees.find({
where: {
date: {gt: new Date('2014-04-01T18:30:00.000Z')}
}
});
有効射程が900メートルを超える武器の最初の3件:
/weapons?filter[where][effectiveRange][gt]=900&filter[limit]=3
可聴域が10未満の武器:
/weapons?filter[where][audibleRange][lt]=10
and / or
以下のコードは、「and」演算子を使って、題名が「My Post」かつ、内容が「Hello」である投稿を検索する例です。
Post.find({where: {and: [{title: 'My Post'}, {content: 'Hello'}]}},
function (err, posts) {
...
});
RESTで等価な検索:
?filter[where][and][0][title]=My%20Post&filter[where][and][1][content]=Hello
以下のコードは、「or」演算子を使って、題名が「My Post」または、内容が「Hello」である投稿を検索する例です。
Post.find({where: {or: [{title: 'My Post'}, {content: 'Hello'}]}},
function (err, posts) {
...
});
より複雑な例として、以下のような式 (field1= foo and field2=bar) OR field1=morefoo
を考えます。
{
or: [
{ and: [{ field1: 'foo' }, { field2: 'bar' }] },
{ field1: 'morefoo' }
]
}
between
between演算子の例:
filter[where][price][between][0]=0&filter[where][price][between][1]=7
Node APIの場合:
Shirts.find({where: {size: {between: [0,7]}}}, function (err, posts) { ... } )
near
where.<field>.near
フィルタは他のフィルタと異なります。多くのwhereフィルタが返されるレコードの数を 制限する 一方で、
near
はSQLのorder by
句のようにレコードを並び替えます。
これを limit
と組み合わせることで、たとえば、特定の場所に最も近い3つのレコード を取得する検索を作成できます。
例えば以下のようにします。
/locations?filter[where][geo][near]=153.536,-28.1&filter[limit]=3
位置情報は、以下のいずれかの方法で表現できます。
location = new GeoPoint({lat: 42.266271, lng: -72.6700016}); // GeoPoint
location = '42.266271,-72.6700016'; // 文字列
location = [42.266271, -72.6700016]; // 配列
location = {lat: 42.266271, lng: -72.6700016}; // オブジェクトリテラル
Restaurants.find({where: {geo: {near: location }}}, function callback(...
near ( 距離による制限 と並び替え)
near フィルタは2つの追加プロパティをとることができます。
maxDistance
unit
maxDistance
がフィルタに含まれると、nearは典型的なwhereフィルタのように動作し、その結果を与えられた距離内のものに限定します。
既定では、maxDistance
は距離をマイル単位で測定します。
与えられた位置情報から2マイル以内にある全てのレストランを見つける例:
var userLocation = new GeoPoint({
lat: 42.266271,
lng: -72.6700016
});
var resultsPromise = Restaurants.find({
where: {
location: {
near: userLocation,
maxDistance: 2
}
}
});
To change the units of measurement, specify unit
property to one of the following:
測定単位を変更するには、unit
プロパティを次のいずれかに指定します。
kilometers
meters
miles
feet
radians
degrees
たとえば、上記の検索をマイルの代わりにキロメートルを使用するように変更するには、次のようにします。
var resultsPromise = Restaurants.find({
where: {
location: {
near: userLocation,
maxDistance: 2,
unit: 'kilometers'
}
}
});
Warning: スペルミスに注意!
unit
の値が誤って入力された場合、例えば 'miles'
の代わりに 'mile'
と入力すると、ループバックは黙ってフィルタを無視します!
like と nlike
like と nlike(not like)演算子を使用すると、SQLの正規表現に一致させることができます。正規表現の形式は、バックエンドのデータソースによって異なります。
like演算子の例:
Post.find({where: {title: {like: 'M.-st'}}}, function (err, posts) { ... });
nlike演算子の例:
Post.find({where: {title: {nlike: 'M.-XY'}}}, function (err, posts) {
memoryコネクタを使うとき:
User.find({where: {name: {like: '%St%'}}}, function (err, posts) { ... });
User.find({where: {name: {nlike: 'M%XY'}}}, function (err, posts) { ... });
大文字小文字を区別しない like と nlike
var pattern = new RegExp('.*'+query+'.*', "i"); /* case-insensitive RegExp search */
Post.find({ where: {title: { like: pattern} } },
REST API経由:
?filter={"where":{"title":{"like":"someth.*","options":"i"}}}
ilike と nilike
ilikeとnilike(not ilike)演算子は、大文字小文字を区別しない正規表現によるマッチを可能にします。これは、memoryコネクタと Postgresqlコネクタでのみサポートされています。
ilike演算子の例:
Post.find({where: {title: {ilike: 'm.-st'}}}, function (err, posts) { ... });
nilike演算子の例:
Post.find({where: {title: {nilike: 'm.-xy'}}}, function (err, posts) {
memoryコネクタを使う場合:
User.find({where: {name: {ilike: '%st%'}}}, function (err, posts) { ... });
User.find({where: {name: {nilike: 's%xy'}}}, function (err, posts) { ... });
Postgresqlコネクタを使う場合:
User.find({where: {name: {ilike: 'john%'}}}, function (err, posts) { ... });
inq
inq 演算子は、指定されたプロパティの値が、与えられた配列の値のいずれかと等しいかどうかを検査します。 一般的な構文は以下のとおりです。
{where: { property: { inq: [val1, val2, ...]}}}
ここで、
- property は、検索されるモデル内のプロパティ(フィールド)の名前です。
- val1, val2 などは配列内のリテラル値です。
inq 演算子の例:
Posts.find({where: {id: {inq: [123, 234]}}},
function (err, p){... });
REST:
/medias?filter[where][keywords][inq]=foo&filter[where][keywords][inq]=bar
または
?filter={"where": {"keywords": {"inq": ["foo", "bar"]}}}