实现细节#

一个 eland.DataFrame 的目标是让熟悉 pandas.DataFrame 的用户能够访问、探索和操作驻留在 Elasticsearch 中的数据。

理想情况下,所有数据都应该驻留在 Elasticsearch 中,而不是驻留在内存中。这限制了 API,但允许访问不适合内存的巨大数据集,并允许使用 Elasticsearch 的强大功能,如聚合。

Pandas 和第三方存储系统#

通常,与 第三方存储系统 (SQL、Google Big Query 等) 的集成涉及访问这些系统并将所有外部数据读入到内存中的 pandas 数据结构中。这也适用于 Apache Arrow 结构。

虽然这提供了对这些系统中数据的访问,但对于大型数据集,这可能需要大量的内存,并且对于像 Elasticsearch 这样的系统,大量导出数据可能是探索数据的低效方式。

另一种选择是创建一个 API,它将类似 pandas.DataFrame 的调用代理到 Elasticsearch 查询和操作。这可以允许 Elasticsearch 集群执行诸如聚合之类的操作,而不是导出所有数据并在内存中执行此操作。

实现选项#

一种选择是将 pandas.DataFrame 后端的内存结构替换为 Elasticsearch 访问器。这将允许完全访问 pandas.DataFrame API。但是,这存在一些问题

  • 如果 pandas.DataFrame 实例映射到一个索引,典型的 pandas.DataFrame 操作可能涉及创建许多派生的 pandas.DataFrame 实例。为每个 pandas.DataFrame 构建索引可能会导致许多 Elasticsearch 索引,并对 Elasticsearch 造成重大负载。例如,df_a = df['a'] 不应该需要 Elasticsearch 索引 dfdf_a

  • 并非所有 pandas.DataFrame API 都映射到我们可能想要在 Elasticsearch 中执行的操作。特别是,涉及将所有数据从 Elasticsearch 导出到内存的 API 调用,例如 df.to_dict()

  • 后端 pandas.DataFrame 结构不容易抽象,并且深度嵌入到实现中。

另一种选择是创建一个 eland.DataFrame API,它模仿 pandas.DataFrame API 的适当方面。这解决了一些上述问题,因为

  • df_a = df['a'] 可以实现为对 Elasticsearch 查询的更改,而不是一个新索引

  • 我们可以支持一个适用于 Elasticsearch 的 pandas.DataFrame API 子集,而不是支持整个 pandas.DataFrame API。如果需要添加调用,我们可以创建一个 eland.DataFrame._to_pandas() 方法,它会明确地将所有数据导出到一个 pandas.DataFrame

  • 创建一个新的 eland.DataFrame API 为我们在实现方面提供了完全的灵活性。但是,它会产生大量工作,这些工作可能会复制许多 pandas 代码 - 例如,打印对象等 - 这会造成维护问题等。