エクササイズ検索API:クエリと6言語の扱い
2026-10-02 · 6 min
GET /v1/exercises/search?q= は、各種目の名前、ターゲット筋、器具を対象に全文検索を行います。照合は完全な単語のみで、送ったすべての単語が必要で、結果は関連度順に並びます。レスポンスの言語は別の選択で、langパラメータが最優先、次にAccept-Languageヘッダー、最後に英語の順で、6言語(en、fr、es、pt、zh、ja)に対応します。検索インデックスは英語のテキストから作られているため、検索語は英語で送り、結果の表示はlangで制御してください。
In short
- 検索の対象は名前、ターゲット筋、器具だけで、手順や補助筋は含まれません。
- 完全な単語で、すべて必須:"squat" は "squats" に一致せず、"squat dumbbell" は両方の単語が必要です。
- 言語の優先順位:?lang= が先、次にAccept-Language、最後に英語。未対応の値はエラーにならず英語になります。
- langは結果の表示を変えるだけで、検索語は翻訳しません。bodyPartなどのフィルターは引き続き英語の値を取ります。
- レスポンスにはContent-LanguageとVary: Accept-Languageが付くので、言語ごとにキャッシュしてください。
種目検索のエンドポイントはどう動きますか?
APIキーを付けてqを送ります。qがないリクエストは400エラーになります。結果は一覧と同じ{ data, pagination }の形で返り、関連度順に並び、同順位はidで決まります。ページは既定で50件、最大100件です。
curl -H "Authorization: Bearer fed_live_YOUR_KEY" \
"https://api.fitexercisedb.com/v1/exercises/search?q=squat&pageSize=10&lang=fr"各結果にはレスポンス項目リファレンスで説明した全項目が含まれます。内部では、種目名、ターゲット筋、器具に対するPostgreSQLの全文検索で、それ以外はインデックスされません。
なぜ "squat" と "squats" で結果が違うのですか?
インデックスにはPostgreSQLのsimpleテキスト設定が使われ、単語は小文字になりますが語幹処理はされません。クエリはplainto_tsqueryで作られ、すべての単語を要求します。そのため、完全な単語だけが一致し、送ったすべての単語が含まれている必要があります。
| クエリ | 動作 |
|---|---|
q=squat | 名前、ターゲット筋、器具にsquatという単語を含む種目 |
q=squat dumbbell | 両方の単語を含む種目のみ |
q=squ | 途中までの単語では何も返りません。前方一致はないため、オートコンプリート用ではありません |
q=abs | ターゲット筋Absと、名前にabsを含む種目の両方に一致 |
入力補完が必要なら、必要な分類と名前を一度読み込んでキャッシュし、ローカルで絞り込み、最後の照会にだけ検索を使います。コードを書く前に、エクササイズデータベースでクエリを試してデータの中身を確認してください。
フランス語、スペイン語、日本語の単語で検索できますか?
クエリを翻訳するやり方では検索できません。検索対象は英語の名前、ターゲット筋、器具で、翻訳された名前はインデックスに含まれないため、他言語の単語は英語と同じつづりのときだけ一致します。langパラメータが変えるのは返ってくる内容であり、照合の対象ではありません。
ローカライズした検索ボックスでは、ユーザーの入力を自分で英語の語に置き換え、そのうえでユーザーの言語のテキストをAPIに求めるのが有効です。
// The user types in French. You map it to English terms, then ask for French text back.
const q = toEnglish("développé couché"); // your own mapping: "bench press"
const url = `/v1/exercises/search?q=${encodeURIComponent(q)}&lang=fr`;よくあるケースでは自由入力を避け、部位、筋肉、器具のドロップダウンを用意し、英語の値をキーにして翻訳したラベルを表示します。
APIはレスポンスの言語をどう選びますか?
3つの情報源を順に確認し、最初に対応しているものが採用されます。どの場合もエラーにはなりません。
| 順序 | 情報源 | 例 |
|---|---|---|
| 1 | クエリパラメータlang | ?lang=fr |
| 2 | Accept-Languageヘッダー(左から右へ読む) | Accept-Language: fr-FR,fr;q=0.9,en;q=0.8 はfrになる |
| 3 | 既定値 | en |
地域サフィックスは無視されるため、fr-FRとpt-BRはfrとptに解決されます。ヘッダーは書かれた順に走査され、最初に対応しているタグが使われ、品質値の比較は行われません。deのような値は未対応で、黙って英語になります。すべてのレスポンスに使用した言語が示されます。
Content-Language: fr
Vary: Accept-Language同じURLでもAccept-Languageによって返るテキストが変わるため、言語をキャッシュキーに含めるか、langを明示的に送ってください。
何が翻訳され、何が英語のままですか?
| データ | langを付けたときの挙動 |
|---|---|
| bodyPart、target、equipment、secondaryMuscles | 固定の語彙から常に翻訳(部位10、ターゲット筋19) |
| name、instructions | 種目ごとに翻訳。翻訳がない場合は英語にフォールバック |
| id、met、カロリー項目、category、difficulty、mechanic、force | 変わりません |
| フィルターの値(bodyPart、target、equipment)とq | 英語のみ |
最後の行が落とし穴です。フランス語のレスポンスでは胸がPoitrineと表示されますが、フィルターが求めるのはChestです。
# the filter value stays English, the labels come back in French
curl -H "Authorization: Bearer fed_live_YOUR_KEY" \
"https://api.fitexercisedb.com/v1/exercises?bodyPart=Chest&lang=fr"フィルター用のリストはlangなしで一度取得し、その値をキーとして保存してください。正確なリストはドキュメントにあります。
FAQ
- 種目検索は手順や補助筋も見ますか?
- いいえ。インデックスの対象は名前、ターゲット筋、器具です。補助筋で絞り込むには、結果を取得してから自分のコードでsecondaryMuscles配列をフィルターしてください。
- deのような未対応のlangを送るとどうなりますか?
- APIは英語にフォールバックして200を返します。実際にどの言語が返ったかは、各種目のlanguage項目かContent-Languageヘッダーで確認できます。
- ?langを送っていてもAccept-Languageは必要ですか?
- いいえ。langクエリパラメータが優先されるため、Accept-Languageはlangがないか未対応のときだけ使われます。
- キャッシュしたレスポンスが違う言語で表示されるのはなぜですか?
- 同じURLでもAccept-Languageによって返るテキストが変わります。レスポンスはVary: Accept-Languageを送るので、キャッシュがそれを尊重するようにするか、URLにlangを加えてください。