使用 boto3 翻阅与特定文件名匹配的 S3 对象

问题描述 投票:0回答:2

我有一个 AWS S3 存储桶,其前缀(或“文件夹”)称为

/photos
。它“包含”一堆图像文件和更少的
EVENT.json
文件。简单的表示可能如下所示:

  • 我的精彩活动桶
    • 照片
      • 图像1.jpg
      • 图像2.jpg
      • 1_EVENT.json
      • 图像3.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对桶中的所有对象进行分页,并根据分页参数进行限制和分页。这意味着我可以轻松获取多个 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 作为前缀,因为响应可能会被其他文件夹中的文件污染。

python amazon-web-services amazon-s3 pagination boto3
2个回答
5
投票

最简单的方法是重新哈希文件名结构,使 EVENT 文件遵循模式

photos/EVENT_*.json
而不是
photos/*_EVENT.json
。 然后您可以使用通用前缀
photos/EVENT

除此之外,我认为您使用的昂贵方法实际上是唯一的方法。


0
投票

您可以在 boto 中的搜索功能之一上添加一个前缀选项。这将大大减少必须扫描的文件量。但是,如果您必须在字符串中间搜索带有通配符的字符串,最后我知道它必须扫描存储桶中的所有对象,那么您将必须通过这些对象进行通配符搜索。

例如:

bucket.search_function(prefix="string")

但我记不起 boto 功能了。

© www.soinside.com 2019 - 2024. All rights reserved.