如何用Lodash orderBy让无排序字段的Firestore文档排列表顶部?
解决Firestore文档按createdAt字段分层排序问题
我来帮你搞定这个排序需求!你的核心问题是要把没有createdAt字段的旧文档优先排在前面,然后有createdAt的新文档按时间从旧到新排列,当前的Lodash orderBy写法把两个逻辑混在一起了,所以结果不符合预期。
问题分析
你现在的代码用了singer.createdAt?? singer.name作为单一排序键,并且按desc排序:
- 对于有createdAt的文档,时间戳(数字)和字符串(name)比较时,数字会被转为字符串,导致排序逻辑混乱;
- 同时
desc排序会让时间戳更大的新文档排在前面,不符合你“从旧到新”的要求。
正确的排序方案
我们需要用多维度排序,分三步处理:
- 优先区分「有无createdAt字段」:没有的排在前面;
- 对有createdAt的文档,按字段值升序排列(旧的时间戳更小,所以升序就是从旧到新);
- 对没有createdAt的文档,可以按name排序(保证稳定),或者随机排序(如果不需要固定顺序)。
调整后的Lodash代码
const sortedSingers = orderBy( singers, [ // 第一维度:无createdAt的文档排在最前 singer => !singer.createdAt, // 第二维度:有createdAt的按旧到新排序(升序) singer => singer.createdAt, // 第三维度:无createdAt的文档按name排序(可选,替换成Math.random()可实现随机) singer => singer.name ], ['desc', 'asc', 'asc'] // 对应每个维度的排序方向 );
代码解释
- 第一维度:
!singer.createdAt会给无createdAt的文档返回true,有则返回false;desc排序下true(数值1)会排在false(数值0)前面,完美实现旧文档优先。 - 第二维度:
singer.createdAt按asc排序,时间戳越小(越旧)的文档越靠前,符合你的需求。 - 第三维度:如果不需要无createdAt文档的固定顺序,把
singer.name换成Math.random()即可实现随机排序,比如:singer => Math.random()
验证示例数据
用你给出的示例数据测试:
- 无createdAt的
Bom和Phil会排在前两位(按name排序的话是Bom→Phil); - 有createdAt的
Tom(190000000)和John(195000000)按升序排列,Tom在前,John在后;
最终结果:Bom, Phil, Tom, John,完全符合你的期望。
内容的提问来源于stack exchange,提问作者Wojciech Król
相关产品推荐
相关产品推荐

