【发布时间】:2016-12-29 05:18:52
【问题描述】:
我有一个 AWS S3 存储桶,其前缀(或“文件夹”)称为 /photos。它“包含”一堆图像文件,甚至更少的EVENT.json 文件。一个幼稚的表示可能如下所示:
- 我的真棒事件桶
- 照片
- image1.jpg
- image2.jpg
- 1_EVENT.json
- image3.jpg
- 2_EVENT.json
- ...
- 照片
EVENT.json 文件有一个对象,其中包含对任意数量图像文件的路径引用,这些文件将图像分组到特定事件中。使用上面的例子,image1.jpg 和 image2.jpg 可能出现在 1_EVENT.json 中,而 image3.jpg 可能属于 2_EVENT.json。
随着存储桶变大,我有兴趣对结果进行分页。我只想在需要时从 S3 一次请求一个页面。我遇到的问题是我想通过包含单词“EVENT”的键专门进行分页。如果不带回所有对象然后过滤或迭代结果,我发现这很难完成。
使用S3 Paginator,我可以进行分页。假设我的 PageSize 和 MaxItems 设置为 6,这就是我可能会在第一页返回的内容:
/photos/
/photos/image1.jpg
/photos/image2.jpg
/photos/1_EVENT.json
/photos/image3.jpg
/photos/2_EVENT.json
S3的扁平化结构是指它按照Prefix对bucket中的所有对象进行分页,根据分页参数进行限制和分页。这意味着我可以轻松获取多个 EVENT.json 文件,或者根本没有,具体取决于页面。
所以我正在寻找更多类似的东西:
/photos/1_EVENT.json
/photos/2_EVENT.json
/photos/3_EVENT.json
/photos/4_EVENT.json
/photos/5_EVENT.json
/photos/6_EVENT.json
无需首先请求所有对象,然后以某种方式对结果集进行切片;这正是我目前正在做的事情:
client = boto3.client('s3')
paginator = client.get_paginator('list_objects_v2')
page_iterator = paginator.paginate(
Bucket=app.config.get('S3_BUCKET'),
Prefix="photos/") # Left PaginationConfig MaxItems & PageSize off intentionally
filtered_iterator = page_iterator.search(
"Contents[?contains(Key, `EVENT`)][]")
for page in filtered_iterator:
# Do stuff.
pass
上面的内容确实很昂贵,没有分页,但它确实给了我一个包含我的“EVENT”搜索字符串的所有文件的列表。
我特别想通过 S3 使用 boto3 对 only EVENT.json 对象的结果进行分页,而无需在每个请求中返回和过滤所有对象的开销。这可能吗?
编辑:我已经将请求范围缩小到带有 photos/ 前缀的对象。这是因为我的存储桶中还有其他“文件夹”也可能包含 EVENT 文件。这使我无法使用 EVENT 或 EVENT.json 作为我的前缀,因为响应可能被其他文件夹中的文件污染。
【问题讨论】:
-
如果您只需要 Amazon S3 内容列表并且不需要它完全最新,您可以使用 Amazon S3 Storage Inventory 将所有文件的每日 CSV 存储在您的 S3 存储桶中。
-
@JohnRotenstein Storage Inventory 似乎没有提供任何有助于分页结果的额外结构,并且仅限于根据 documentation 的前缀进行编目。但是,如果我可以使用它来创建和维护仅包含给定前缀的 EVENT 文件的清单,那么计划的清单可能值得等待。
标签: python amazon-web-services amazon-s3 paging boto3