2016-12-29 87 views
1

我有一个名为/photos的前缀(或“文件夹”)的AWS S3存储桶。该“包含”一堆图像文件,甚至更少EVENT.json文件。一个天真的表示可能是这样的:通过S3对象使用boto3匹配特定文件名的页面

  • 我-真棒事件斗
    • 照片
      • 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.json对象通过S3使用boto3而没有返回和过滤所有对象的开销每个请求。那可能吗?

编辑:我已经把请求缩小到只与photos/前缀对象。这是因为我的存储桶中还有其他“文件夹”也可能包含EVENT文件。这阻止我使用EVENT或EVENT。json作为我的前缀,因为响应可能会受到来自其他文件夹的文件的污染。

+0

如果您只需要一个Amazon S3内容列表,并且您不需要它完美地更新,就可以使用[Amazon S3 Storage Inventory](http://docs.aws.amazon.com/AmazonS3/ latest/dev/storage-inventory.html)来存储S3存储桶中所有文件的每日CSV。 –

+0

@JohnRotenstein存储清单似乎没有提供任何有助于分页结果的附加结构,并且仅限于根据[文档](http://docs.aws.amazon.com/AmazonS3/latest /dev/storage-inventory.html#storage-inventory-how-to-set-up)。但是,如果我可以使用它来创建和维护具有给定前缀的EVENT文件的清单,则排定的清单可能值得等待。 – afilbert

回答

2

最简单的方法是重新构建您的文件名结构以使EVENT文件遵循模式photos/EVENT_*.json而不是photos/*_EVENT.json。然后你可以使用一个通用的前缀photos/EVENT

简而言之,我认为你使用的昂贵的方法实际上是唯一的方法去解决它。

+0

请使用'\'反引号\''来转义文件名; '*这里*之间的东西*呈现为斜体文字。 –

+0

不幸的是,这些文件名是在我进入项目之前开发的应用程序生成的。它已经在客户流通中,并且很难改变。经过一段时间的研究之后,我得出结论,我要么改变我们如何命名和组织文件,就像你所建议的那样,要么解决恢复所有对象的开销。我不应该感到惊讶,因为“简单”是以S3服务的名义。我正在研究通过RDS缓存和分页结果。 – afilbert

0

有一个前缀选项,你可以在博托的其中一个搜索功能上抛出。这将大大减少它必须扫描的文件数量。然而,如果你不得不在字符串的最后搜索带有通配符的字符串,我知道它必须扫描桶中的所有对象,然后你必须通过通配符来搜索那些对象。

例如:

bucket.search_function(prefix="string") 

我不能,虽然召回博托功能关闭我的头顶。

+0

我很遗憾已经使用前缀来限制我的结果到/ photos“文件夹”,否则我会使用EVENT作为前缀并将其称为一天。不幸的是,在同一个桶中的其他“文件夹”中也有EVENT文件,我想避免污染我的/照片事件。 – afilbert