複雑なRESTful検索メソッドを実行する適切な方法は何ですか?


44

RESTの原則に従って、いくつかの基準を使用して検索を行い、結果をクライアントに返すAPIのGETメソッドを作成します。問題は、基準に最大14個のパラメーターを設定できることです。そのうちの1つは複雑なオブジェクトのリストです。

  • これらの複雑なオブジェクトをURLパラメータとの間でエンコード/デコードできるかどうかさえわかりません。

  • URLが取得できる時間は計算しませんでしたが、十分に大きく、URLの長さの制限に達すると確信していますか?

また、検索は結果を「リアルタイム」で表示する必要があります。つまり、ユーザーが検索フォームから何かを変更するたびに、「検索」ボタンを押さなくても新しい結果を表示できるはずです。

これらの点を明確にして、多くのパラメーターを使用して安らかな検索方法を作成することをお勧めしますか?


3
余談ですが(執筆時点で2つの回答のいずれもリアルタイム部分に言及していないことに注意してください)、リアルタイム検索は通常、更新されたリクエストを何度も送信する必要があります。例えば、あなたしているタイピングしながら、あなたは次のようなもののために要求を送信することだろうsearch?q=tsearch?q=tesearch?q=test、など。サーバーを傷つけないように、クエリの送信頻度を制限することを検討してください。または、大量の情報を返し、クライアント側でフィルタリングを行うこともできます。ユーザーが物事を大幅に絞り込むことができる幅広いカテゴリを入力した場合、それはうまく機能します。
キャット

2
ソリューションに関係なく、テクノロジーに依存しない形式でデータを交換してください。したがって、内部表現を使用しないでください。使用すると、APIのクライアントを作成するのが難しくなります。
-Kwebble

必要に応じて、このライブラリはgithub.com/jirutka/rsql-parserを実行できます。JPAを使用する場合はJPA拡張機能があります。または、独自の訪問者を作成して、検索エンジンのAPIにマップすることができます。また、独自の演算子を追加できます。
ウォルフラット

回答:


54

あなたが私の答えを読む前に、@ Neilに同意したと言いたいです。戦いを選択する必要があります。私たちは通常、最善を尽くしたいと考えていますが、時には議論の余地が少なすぎて、意思に反した決定を下す必要があります。

とにかく、ニールの答えで、私はもう一つのことを見逃しています。ドキュメント。開発者がPOSTリクエスト/searchが安全であることを確認するためだけです。

そうは言った。

1. GETする機会を与える

GET最初にオプションを検討してください。この質問URLの最大長を確認してください。最長のクエリ文字列が2000文字より長いかどうかを評価します。そうでなく、そうなると思わない場合は、に進みGETます。いように見えるかもしれませんが、少なくともURLをブックマークできます。もちろん、メソッドのセマンティクス(べき等、安全、キャッシュ)から派生したすべての利点があります。

1.1クエリ文字列をエンコードしてみてください

たとえば、base64。javascript でもbase 64エンコーディングがサポートされています

これがどのように機能するかです:

  1. すべてのフィルターを使用してJSONを構築し、正規化します。
  2. 文字列に解析する
  3. エンコードする
  4. エンコードされたJSONを要求パラメーター(/search?q=SGVsbG8gV29ybGQh....)として送信します。
  5. サーバー側で、パラメーターqをデコードします。
  6. JSON文字列をデシリアライズします

以前は、可能な限り長いJSON文字列を作成し、エンコードして長さを取得していました。エンコードされた文字列がURLに収まるかどうかを評価します。テストするために、Fiddle.jsに次のスニペットを実装しました。(私はそれがまだうまくいくことを願っています)1

Base 64エンコードは確定的で可逆的であるため、衝突の可能性はありません。

エンコードされたクエリを使用すると、検索をDBに保存したり、URLをブックマークしたり、リンクを共有したりすることもできます。もちろん、文字列をエスケープ/エスケープする必要はありません。

1.2エイリアスで試してください

REST APIの設計方法に関するこのブログを読んで、もう1つの選択肢を思い出しました。一般的なクエリのエイリアス

これらは次の理由で面白いと思う

  • クエリ文字列の長さを短くしてください。APIをよりクリーンで使いやすいものにします

    GET / tickets /?status = closed&closedAt = xxx vs GET / tickets / recently-closed /

  • より多くのエイリアスまたはより多くの要求パラメーターと組み合わせ可能。

    GET / tickets /?status = closed&closedAt = xxx&within = 30min vs GET / tickets / recently-closed /?within = 30min

  • エイリアスとエンコードされたクエリ文字列を組み合わせることができます

    GET / tickets /?status = closed&closedAt = xxx&within = 30min vs GET / tickets / recently-closed /?q = SGVsbG8g ...


1:JSONを使用しましたが、サーバー側でデシリアライズできるとすぐに他の形式を使用できます。


2
これは実用的かつ正しいことです。また、ほとんどのプログラミング言語では、ハッシュをクエリ文字列に簡単に変換できるため、GETアクションから始めるのは非常に簡単です。
アルアンハダッド

1
私はSpringoveroverflow.com/questions/16942193/が大好きです…最初の試行でうまくいったとは信じられません:D。URLの長さについては1k未満ですが、まだ仕様を反復する必要があります。
anat0lius

次に、GETを使用します。簡単にするために。Spring MVCを使用すると、GETでまったく同じマッピングを実現できます。SpringのWebArgumentResolverを探してください;-)
Laiv

Base64は、ペイロードサイズを約4/3増やします。urlencodingは特殊文字については3/1にすることができますが、ほとんど安全な文字を使用したクエリは同じサイズを維持します。base64を使用する他の理由はありますか?
villasv

あんまり。エスケープURLが嫌いです。ペイロードの過剰は、ここでのトレードオフです。リクエストごとのGETの最大サイズ内に収まる必要があります。それがスニペットを作成した理由です。ユーザーが試してみてください。答えを書いたとき、実装の詳細よりもWebセマンティクスを優先しました。答えの全体のポイントは、「GETで試行し続ける」ことです。あなたの方法を見つけるか、私があなたと共有するこれらのいずれかを使用してください。
ライヴ

13

ハンマーしか持っていない場合、すべてが釘のように見えます。ここでの問題は、検索ページをRESTfulなページに変えようとしていることであり、これはRESTfulなデザインが解決する一般的なパターンではないようです。

バックエンドから必要な情報を取得するために、ユーザーが提供するパラメーターを使用してPOSTリクエストを送信するだけです。検索を実行する以外に何もする必要がないと思うので、このページから挿入する必要はありません。ただ、追加/あなた/ユーザーページとの競合に実行するためにリスクはありませんので、あなたのURLの最後に検索します RESTfulなこと。


2
@LiLou_:その要件には、現実的な可能性は2つしかありません。1. すべてのデータをフロントエンドに読み込み、そこでフィルタリングを行います。これにより、必要なメモリ量が制限される場合があります。2.検索条件の変更ごとにサーバーに新しいリクエストを行います。これがPOSTリクエストであるかGETリクエストであるかは関係ありませんが、関連するネットワークレイテンシは、ユーザーの「リアルタイム」更新の感覚にとって混乱を招く可能性があります。
バートヴァンインゲンシェナウ

2
私は同意しないことに同意します、POSTは意味的に何かを意味します。パラメータが多すぎる場合は、GETを使用して、クエリパラメータですべてのフィルタデータを渡すことをお勧めします。これは、アプリケーションレベルでの障害です。
CodeYogi

2
@CodeYogiの場合、顧客は議論の余地を与えないことがあります。それぞれが独自のフィルターを備えた40〜50列のExcelのようなビューページを実装しました。そして、もちろんソート可能です。とにかく、GETでまだ可能ですが、それはあまり流行ではないかもしれません
-Laiv

1
@Laivはその場合、POSTはサーバーの状態の変化を意味するため、真剣な議論が必要です。このような使用例は例外ではないため、ハッキングなしで処理する必要があります。
CodeYogi

2
これらの場合、ドキュメントは必須です。お客様のアプリケーションの使いやすさについて、お客様と真剣に話し合いました。エンドユーザーが同意してくれたので、後で正しいことが証明されました。ただし、時には戦いを選ぶ必要があります。
ライヴ

0

それは、APIモデルが何であるか、またはなしとして動詞として完全に異なります。

APIがnoneの場合、次のようにオブジェクトのリストを取得できます。

GET: /api/v1/objects

この場合、データを要求パラメーターとして送信する必要があります。そのため、パラメーターをKey-Valueのフラットリストとして記述する必要があります。

GET: /api/v1/objects

key1 : val1
key2.key1 : val 21
key2.key2 : val 22
....

一部のプラットフォームは、カスタムパラメーターリゾルバー(Spring MVCなど)をサポートしています。これは、パラメーターをオブジェクトに変換できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.