使用 boto3 通过与特定文件名匹配的 S3 对象分页
Page through S3 objects matching specific filename using boto3
我有一个名为 /photos
的带前缀(或 "folder")的 AWS S3 存储桶。 "contains" 一堆图像文件和更少的 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 个文件,或者 none 个文件,具体取决于页面。
所以我正在寻找更多类似的东西:
/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 分页 仅 EVENT.json 对象的结果,而无需在每次请求时返回和过滤所有对象的开销。这可能吗?
编辑:我已经将请求范围缩小到仅具有 photos/
前缀的对象。这是因为我的存储桶中还有其他 "folders" 也可能包含 EVENT 文件。这阻止我使用 EVENT 或 EVENT.json 作为我的前缀,因为响应可能被其他文件夹中的文件污染。
最简单的方法是重新散列文件名结构,使 EVENT 文件遵循模式 photos/EVENT_*.json
而不是 photos/*_EVENT.json
。然后你可以使用 photos/EVENT
.
的通用前缀
除此之外,我认为您使用的昂贵方法实际上是解决此问题的唯一方法。
有一个前缀选项,您可以在 boto 的搜索功能之一上使用。这将大大减少它必须扫描的文件数量。但是,如果您最后必须在字符串中间使用通配符搜索字符串,我知道它必须扫描存储桶中的所有对象,那么您将不得不通过这些对象进行通配符搜索。
例如:
bucket.search_function(prefix="string")
不过我记不起 boto 函数了。
我有一个名为 /photos
的带前缀(或 "folder")的 AWS S3 存储桶。 "contains" 一堆图像文件和更少的 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 个文件,或者 none 个文件,具体取决于页面。
所以我正在寻找更多类似的东西:
/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 分页 仅 EVENT.json 对象的结果,而无需在每次请求时返回和过滤所有对象的开销。这可能吗?
编辑:我已经将请求范围缩小到仅具有 photos/
前缀的对象。这是因为我的存储桶中还有其他 "folders" 也可能包含 EVENT 文件。这阻止我使用 EVENT 或 EVENT.json 作为我的前缀,因为响应可能被其他文件夹中的文件污染。
最简单的方法是重新散列文件名结构,使 EVENT 文件遵循模式 photos/EVENT_*.json
而不是 photos/*_EVENT.json
。然后你可以使用 photos/EVENT
.
除此之外,我认为您使用的昂贵方法实际上是解决此问题的唯一方法。
有一个前缀选项,您可以在 boto 的搜索功能之一上使用。这将大大减少它必须扫描的文件数量。但是,如果您最后必须在字符串中间使用通配符搜索字符串,我知道它必须扫描存储桶中的所有对象,那么您将不得不通过这些对象进行通配符搜索。
例如:
bucket.search_function(prefix="string")
不过我记不起 boto 函数了。