我有一个 AWS S3 存储桶,其前缀(或“文件夹”)称为
/photos
。它“包含”一堆图像文件和更少的 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对桶中的所有对象进行分页,并根据分页参数进行限制和分页。这意味着我可以轻松获取多个 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”搜索字符串的所有文件的列表。
我特别想使用 boto3 通过 S3 对 only EVENT.json 对象的结果进行分页,而无需在每次请求时返回和过滤所有对象。这可能吗?
编辑:我已经将请求范围缩小到仅带有
photos/
前缀的对象。这是因为我的存储桶中还有其他“文件夹”也可能包含事件文件。这阻止我使用 EVENT 或 EVENT.json 作为前缀,因为响应可能会被其他文件夹中的文件污染。
最简单的方法是重新哈希文件名结构,使 EVENT 文件遵循模式
photos/EVENT_*.json
而不是 photos/*_EVENT.json
。 然后您可以使用通用前缀 photos/EVENT
。
除此之外,我认为您使用的昂贵方法实际上是唯一的方法。
您可以在 boto 中的搜索功能之一上添加一个前缀选项。这将大大减少必须扫描的文件量。但是,如果您必须在字符串中间搜索带有通配符的字符串,最后我知道它必须扫描存储桶中的所有对象,那么您将必须通过这些对象进行通配符搜索。
例如:
bucket.search_function(prefix="string")
但我记不起 boto 功能了。