有时候会碰到种需求,要求对来自多个接口的数据进行合并查询并排序分页。
既然不在一张表中,而且需要排序,就很难通过一次查询解决从多个数据源中获取数据并保证正确排序并分页,多次查询是不可避免的,关键在于如何正确的合并数据和减少查询的次数。
当然,这种需求应该尽可能的避免,除非没有选择。
说下关键:
- 初次查询的定位。
- 判断应该从哪个数据源获取更多的数据。
- 合并数据。
- 二分查找法减少查询次数。
1. 确定总需要的数据量
- 计算目标页的记录数:
- 目标页码 (
desiredPage
):用户希望获取的页码(从1开始)。 - 每页大小 (
pageSize
):每页显示的记录数。 - 总需要的数据量 (
totalNeeded
):
[
\text{totalNeeded} = \text{desiredPage} \times \text{pageSize}
]
- 目标页码 (
2. 分配数据获取量到各数据源
- 确定数据源数量:
- 数据源数量 (
numberOfDataSources
):参与查询的独立数据源的数量。
- 数据源数量 (
- 均匀分配数据量:
- 将
totalNeeded
均匀分配到每个数据源,确保每个数据源都有机会贡献数据。
[
\text{initialPageSizePerSource} = \lceil \frac{\text{totalNeeded}}{\text{numberOfDataSources}} \rceil
] - 说明:使用向上取整,确保每个数据源至少获取足够的数据。
- 将
3. 计算每个数据源需要获取的页数
- 页数计算:
- 根据每个数据源的
pageSize
,计算需要获取的页数。
[
\text{pagesNeededPerSource} = \lceil \frac{\text{initialPageSizePerSource}}{\text{pageSize}} \rceil
] - 说明:确保每个数据源获取足够的页数,以满足分配的记录量。
- 根据每个数据源的
4. 初始数据获取
- 从第一页开始:
- 对于每个数据源,从第一页 (
page=1
) 开始,获取pagesNeededPerSource
页的数据。
- 对于每个数据源,从第一页 (
- 并行获取:
- 利用异步或并行处理,从所有数据源同时获取数据,提高效率。
- 收集数据:
- 将每个数据源返回的记录集合并到一个统一的列表中。
5. 合并与排序
- 数据合并:
- 将所有数据源返回的记录合并成一个整体列表。
- 数据排序:
- 根据指定的排序字段和顺序(如
reply_count
、like_count
等),对合并后的数据进行排序,确保数据的顺序符合需求。
- 根据指定的排序字段和顺序(如
6. 动态获取更多数据(如有必要)
- 检查数据量:
- 如果合并后的数据量小于
totalNeeded
,需要从数据源获取更多数据。
- 如果合并后的数据量小于
- 继续获取策略:
- 维护当前页数:跟踪每个数据源已经获取的页数。
- 数据源选择:
- 根据现有数据的分布,决定从哪个数据源继续获取下一页的数据,以确保数据的连续性和完整性。
- 示例:
- 比较各数据源的最后一条记录与其他数据源的第一条记录,决定优先从哪些数据源获取更多数据。
- 重复获取:
- 继续从选定的数据源获取数据,直到合并后的数据量满足
totalNeeded
或所有数据源均无更多数据可供获取。
- 继续从选定的数据源获取数据,直到合并后的数据量满足
7. 计算需要跳过的记录数
- 跳过记录数:
- 目标页的起始索引为:
[
\text{targetStartIndex} = (\text{desiredPage} - 1) \times \text{pageSize}
] - 跳过逻辑:
- 将合并后的数据列表视为一个整体,直接跳过前
targetStartIndex
条记录,以获取目标页的数据。
- 将合并后的数据列表视为一个整体,直接跳过前
- 说明:无需分别计算每个数据源需要跳过的记录数,而是统一在合并后的列表中进行跳过操作。
- 目标页的起始索引为:
8. 提取目标页的数据
- 数据提取:
- 从合并并排序后的数据列表中,跳过
targetStartIndex
条记录,获取接下来的pageSize
条记录,作为目标页的数据。
- 从合并并排序后的数据列表中,跳过
- 处理不足情况:
- 如果合并后的数据不足以覆盖目标页,则返回实际可获取的记录数,可能导致返回的页数据少于
pageSize
。
- 如果合并后的数据不足以覆盖目标页,则返回实际可获取的记录数,可能导致返回的页数据少于
关键规则总结
-
均衡数据分配:
- 将总需要的数据量均匀分配到所有数据源,确保每个数据源都有机会贡献数据,避免数据遗漏。
-
动态调整查询:
- 根据初始获取的数据量,动态决定是否需要继续从某些数据源获取更多数据,以满足目标页的数据需求。
-
统一跳过逻辑:
- 在合并后的数据列表中统一计算并跳过所需的记录数,简化分页逻辑,避免复杂的跨数据源跳过计算。
-
排序与合并一致性:
- 在合并数据后进行统一排序,确保不同数据源的数据能够正确地按照业务需求排序,避免数据混乱。
-
并行数据获取:
- 利用并行或异步机制从多个数据源同时获取数据,提高整体查询效率,减少响应时间。
-
健壮的错误处理:
- 在数据获取过程中,处理可能出现的异常,如某个数据源无法响应,确保系统的健壮性和容错性。
-
详细的日志记录:
- 记录每一步的数据获取、合并、排序和提取过程,便于后续的调试和性能分析。
总结
总的来说,对于多个数据源使用筛选条件缩小在一万以内的,通常最多需要查询3~5次。在一千以内可以在2到3次,勉强可以接受吧。