实现细节#
一个 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 索引df
和df_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
代码 - 例如,打印对象等 - 这会造成维护问题等。