【问题标题】:AWS S3 list keys begins with a stringAWS S3 列表键以字符串开头
【发布时间】:2021-02-18 20:55:57
【问题描述】:

我在 AWS Lambda 函数中使用 python 来列出以特定 id 开头的 s3 存储桶中的键

for object in mybucket.objects.all():
            file_name = os.path.basename(object.key)
            match_id = file_name.split('_', 1)[0]

问题是如果一个 s3 存储桶有几千个文件,迭代效率非常低,有时 lambda 函数会超时

这是一个示例文件名

https://s3.console.aws.amazon.com/s3/object/bucket-name/012345_abc_happy.jpg

我只想迭代键名中包含“012345”的对象 关于我如何实现这一点的任何好的建议

【问题讨论】:

  • 这个问题重复使用 contains 这个词,而它的意思似乎是 begins with。 这是一个非常重要的区别,因为接受的答案只有正确的 begins with -- 它是 contains 的子集。 S3 仅支持前缀匹配(以开头)而不支持字符串匹配(包含)键列表。
  • @Michael-sqlbot 3 年后这个功能限制仍然存在吗?我也想通过键搜索,但我感兴趣的字符串在中间,而不是结尾。
  • @user554481 不支持扫描键空间,这是在对象键中间查找匹配项所必需的。想想电话簿。尝试在此类书中按名字(而不是姓氏)查找某人,您会立即看到问题的本质。
  • 我可以看到 AWS 对其键进行全表扫描是多么费力,但是当像 OP 这样的用户必须扫描所有对象时,这不是经常发生的事情吗一个rest API并对客户端的所有键执行文本搜索?

标签: python amazon-web-services amazon-s3 aws-lambda


【解决方案1】:

这是你需要解决的方法。

S3 将所有内容都存储为对象,并且没有文件夹或文件名。一切都是为了方便用户。

aws s3 ls s3://bucket/folder1/folder2/filenamepart --recursive

将获取与该名称匹配的所有 s3 对象名称。

import boto3
s3 = boto3.resource('s3')
my_bucket = s3.Bucket('bucketname')
for obj in my_bucket.objects.filter(Prefix='012345'):
    print(obj)

为了加快列表速度,您可以并行运行多个脚本。

希望对你有帮助。

【讨论】:

    【解决方案2】:

    您可以通过删除 os 并使用字符串方法将速度提高 30-40%。
    根据您可以对文件路径字符串做出的假设,您可以获得额外的加速:

    使用os.path.basename()

    %%timeit
    match = "012345"
    fname = "https://s3.console.aws.amazon.com/s3/object/bucket-name/012345_abc_happy.jpg"
    os.path.basename(fname).split("_")[0] == match
    
    # 1.03 µs ± 29.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
    

    没有os,先在/上拆分,再在_上拆分:

    %%timeit
    match = "012345"
    fname = "https://s3.console.aws.amazon.com/s3/object/bucket-name/012345_abc_happy.jpg"
    fname.split("/")[-1].split("_")[0] == match
    
    # 657 ns ± 11.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
    

    如果您知道实际文件名中只有一个下划线,则可以只使用一个split()

    %%timeit
    match = "012345"
    fname = "https://s3.console.aws.amazon.com/s3/object/bucket-name/012345_abc_happy.jpg"
    fname.split("_")[0][-6:] == match
    
    # 388 ns ± 5.65 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-28
      • 1970-01-01
      • 1970-01-01
      • 2022-07-16
      • 1970-01-01
      • 1970-01-01
      • 2021-11-18
      相关资源
      最近更新 更多