ニフクラ mobile backend(mBaaS)お役立ちブログ

スマホアプリ開発にニフクラ mobile backend(mBaaS)。アプリ開発に役立つ情報をおとどけ!

複数データを取得する際にはIN検索を使いましょう

f:id:mbaasdevrel:20180913163950p:plain

データストアの利用テクニックの紹介です。

データストアから複数のデータを取得する際には条件を指定します。ある数字以上、ある日付よりも前といった条件指定ができますが、中には飛び飛びでデータを指定したい場合もあります。そうした時の方法としてOR検索とIN検索が用意されています。

今回はこの2つの検索処理の違いを紹介します。

結論

In検索を使いましょう。

OR検索での実装

たとえばOR検索の実装を次のようにしています。データ件数は1万件程度です。特定のobjectIdをイコール検索で指定し、それを100件つなげています。つまりデータは100件返ってきます。

const Chat = ncmb.DataStore('Data');
const chats = await Chat.limit(100).fetchAll()
const ary = chats.map(c => Chat.equalTo('objectId', c.objectId));
const results = await Chat.or(ary).limit(100).fetchAll();

IN検索での実装

次にIN検索での実装です。

const Chat = ncmb.DataStore('Data');
const chats = await Chat.limit(161).fetchAll()
const ids = chats.map(c => c.objectId);
const results = await Chat.in('objectId', ids).limit(100).fetchAll();

実行結果

20回実行した平均時間は次の通りです。

  • OR検索:368ms
  • IN検索:221.9ms

データが10,000件程度のクラスで1.6倍時間が変わってきます。データストアに対する負荷もORの方が高いので、対象データ件数が増えれば増えるほど、負荷が高くなっていきます。

SQLでいえば…

OR検索もIN検索もSQLに同じ構文があります。AまたはBまたはCのデータを検索する際に、SQLでいえば次のようになるでしょう。

  • OR検索:FIELD = 'A' OR FIELD = 'B' OR FIELD = 'C'
  • IN検索:FIELD IN ('a', 'b', 'c')

こうした条件に加えて別な絞り込み条件を追加したりすることを想定すると、シンプルなIN検索を使った方が分かりやすいはずです。

OR検索の文字数限界

検索処理を行うREST APIはGETとなっています。そのため、クエリー文字列が長くなり過ぎるとエラーになります。試した限り、162件を超えるとobjectIdで検索するとエラーになってしまいました。

(node:57649) UnhandledPromiseRejectionWarning: Error: cannot GET /2013-09-01/classes/Data?where=%7B%22%24or%22%3A%5B%7B%22objectId%22...%7D&limit=1000 (414)
  :
(Use `node --trace-warnings ...` to show where the warning was created)
(node:57649) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:57649) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

IN検索であれば、クエリー文字列も減りますので、もっとデータを取得できるでしょう。

まとめ

パフォーマンスの高いアプリを開発する際には絞り込み条件やインデックスを有効活用してください。シンプルな絞り込み条件を指定すれば、それだけレスポンスも高速になるはずです。

中津川 篤司

中津川 篤司

NCMBエヴァンジェリスト。プログラマ、エンジニアとしていくつかの企業で働き、28歳のときに独立。 2004年、まだ情報が少なかったオープンソースソフトの技術ブログ「MOONGIFT」を開設し、毎日情報を発信している。2013年に法人化、ビジネスとエンジニアを結ぶDXエージェンシー「DevRel」活動をスタート。