Firebase Realtime Database大数值场景下Query查询失效问题
问题原因
核心问题是Firebase Realtime Database对字符串类型字段执行字典序比较,而非你预期的数值大小比较:
- 你将
sl、tp字段存储为带前缀的字符串格式,查询时的区间边界也是字符串类型 - 你设置的
buy_sl查询上限是buy_sl_100000000,该字符串首字符为1,当价格数值超过1后,比如BTC订单的sl值为buy_sl_34887,首字符为3,按字典序buy_sl_34887>buy_sl_100000000,导致查询区间startAt(buy_sl_34886)到endAt(buy_sl_100000000)实际为无效区间(起始值大于结束值),因此返回空结果 - 小数值场景下价格首字符为
1,和上限字符串首字符一致,字典序比较结果刚好和数值序结果匹配,所以功能正常
解决方法
方案一(最优推荐):改为数值类型存储
去掉sl、tp字段的字符串前缀,直接存储纯数值类型的价格,新增单独字段标记订单买卖方向即可,查询逻辑改为:
function GetBuyList(symbol, currentPrice) { // 买单tp <= 当前价触发 var buy_tp = db.ref(`orders/active_orders/${symbol}`).orderByChild("tp").startAt(0).endAt(currentPrice) // 买单sl >= 当前价触发 var buy_sl = db.ref(`orders/active_orders/${symbol}`).orderByChild("sl").startAt(currentPrice).endAt(100000000) buy_tp.once("value", function (snapshot) { if (snapshot.val() !== null) { ProcessOrders(snapshot.val(), 'tpHit', currentPrice) } }); buy_sl.once("value", function (snapshot) { if (snapshot.val() !== null) { ProcessOrders(snapshot.val(), 'slHit', currentPrice) } }); }
数值类型的比较完全匹配业务逻辑,不会出现排序异常问题。
方案二(兼容现有存储):固定长度字符串对齐
如果不希望修改现有存储结构,可将所有价格部分补为固定长度的字符串,比如统一为8位整数+4位小数,不足位前面补0,例如:
- 34887 转为
buy_sl_00034887.0000 - 1.21 转为
buy_sl_00000001.2100
查询上限改为buy_sl_99999999.9999,同时查询时生成的边界字符串也要做相同的补零对齐处理,即可保证字典序和数值序一致。
内容的提问来源于stack exchange,提问作者Jeffy Lee
相关产品推荐
相关产品推荐

