查询时如何调用JSON文件动态汇率将本币价格换算为USD实现筛选
解决方案
核心结论
你完全可以直接使用当前已读取的JSON汇率数据在查询阶段完成换算筛选,不需要额外创建汇率表,现有cron同步汇率文件的方案已经可以满足需求。
推荐实现方案(数据库查询阶段完成筛选,性能最优)
前置说明
- 你的JSON汇率数据中
inverseRate字段含义为1单位当地货币可兑换的USD金额,直接用该字段做换算即可 - 先给汇率数据补全USD本身的配置,避免本位币记录被漏查:
// 读取汇率后添加USD配置 $this->rates['usd'] = [ 'code' => 'USD', 'rate' => 1, 'inverseRate' => 1 ];
- 先映射前端选项对应的USD价格区间:
$usdRangeMap = [ '1' => ['min' => 0, 'max' => 5], '2' => ['min' => 5, 'max' => 10], // 后续新增区间直接在该处补充即可 ]; $selectedRanges = array_map(fn($val) => $usdRangeMap[$val], $this->fee);
完整查询逻辑
$this->teachers = User::where('user_type','tutor') ->orderBy('created_at','desc') ->whereHas('Teacher', function($query) use ($selectedRanges) { $query->when($this->fee, function($query) use ($selectedRanges) { // 嵌套where避免条件冲突 $query->where(function ($rangeQuery) use ($selectedRanges) { foreach ($selectedRanges as $range) { $rangeQuery->orWhere(function ($currencyQuery) use ($range) { // 遍历所有货币,拼接对应换算条件 foreach ($this->rates as $currencyKey => $rateInfo) { $currencyQuery->orWhere(function ($q) use ($range, $currencyKey, $rateInfo) { $q->where('fee->currency', strtoupper($currencyKey)) // 当地货币最小费用换算为USD后 >= 区间下限 ->whereRaw('(fee->>"$.min_fee") * ? >= ?', [ $rateInfo['inverseRate'], $range['min'] ]) // 当地货币最大费用换算为USD后 <= 区间上限 ->whereRaw('(fee->>"$.max_fee") * ? <= ?', [ $rateInfo['inverseRate'], $range['max'] ]); }); } }); } }); }); }) ->paginate(15);
注:
fee->>"$.min_fee"是MySQL支持的JSON字段取值简写,等同于JSON_UNQUOTE(JSON_EXTRACT(fee, "$.min_fee")),如果使用其他数据库调整对应JSON取值语法即可。
可选优化点
- 可以把每日同步的汇率数据加到缓存中(比如Laravel的文件缓存、Redis缓存),避免每次请求都读取本地磁盘文件,性能更好
- 注意你贴出的
rates.json末尾笔误写了],实际应该是},否则JSON解析会失败
内容的提问来源于stack exchange,提问作者Орлов Владлен
相关产品推荐
相关产品推荐

