使用boto3

时间:2016-12-29 05:18:52

标签: python amazon-web-services amazon-s3 paging boto3

我有一个带有前缀(或"文件夹")的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,我能够进行分页工作。假设我的PageSizeMaxItems设置为6,这就是我可能会在第一页上找到的内容:

/photos/
/photos/image1.jpg
/photos/image2.jpg
/photos/1_EVENT.json
/photos/image3.jpg
/photos/2_EVENT.json

S3的扁平结构意味着它根据前缀对桶中的所有对象进行分页,并根据分页参数进行限制和分页。这意味着我可以轻松地获取多个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分页 EVENT.json对象的结果,而不会在每次请求时返回和过滤所有对象。这可能吗?

编辑:我已经将请求缩小到只有photos/前缀的对象。这是因为还有其他"文件夹"在我的桶中也可能包含EVENT文件。这使我无法使用EVENT或EVENT.json作为我的前缀,因为响应可能会受到来自其他文件夹的文件的污染。

2 个答案:

答案 0 :(得分:3)

最简单的方法是重新运行文件名结构,使EVENT文件遵循模式photos/EVENT_*.json而不是photos/*_EVENT.json。然后,您可以使用photos/EVENT的公共前缀。

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

答案 1 :(得分:0)

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

例如:

$('body').click('.dropdown-menu li a[href="#"]', function(e) {e.preventDefault() });

虽然我无法回想起boto功能。