FitExerciseDB

动作搜索 API:查询规则与 6 种语言

2026-10-02 · 6 min

GET /v1/exercises/search?q= 会对每个动作的名称、目标肌群和器械做全文搜索。它只匹配完整单词,要求你发送的每个词都出现,并按相关度排序。响应语言是另一项独立选择:lang 参数优先,其次是 Accept-Language 请求头,最后是英语,共支持六种语言(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 如何选择响应语言?

系统按顺序检查三个来源,取第一个受支持的,任何情况都不会报错:

顺序来源示例
1查询参数 lang?lang=fr
2Accept-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 数组。
如果我发送不支持的 lang(例如 de)会怎样?
API 会回退到英语并返回 200。请查看每个动作的 language 字段或 Content-Language 响应头,确认实际拿到的语言。
已经发送 ?lang 还需要 Accept-Language 吗?
不需要。lang 查询参数优先,只有在 lang 缺失或不受支持时才会使用 Accept-Language。
为什么缓存的响应显示了错误的语言?
同一个 URL 会因 Accept-Language 不同而返回不同文本。响应会发送 Vary: Accept-Language,请让你的缓存遵守它,或在 URL 中加入 lang。