如何在亚马逊S3存储桶中进行全文搜索?

36

我在S3上有一个存储桶,在其中有大量文本文件。

我想要在文本文件中搜索某些文本。它只包含原始数据,而且每个文本文件都有不同的名称。

例如,我有一个存储桶名称:

abc/myfolder/abac.txt

xyx/myfolder1/axc.txt

& 我想在上述文本文件中搜索文本“我是人类”。

如何做到这一点?这是否可能?


2
你必须一个一个地请求所有的文件;毕竟它不是关系型数据库。 - Ja͢ck
如果我有10万个文件,那么我的搜索速度会变得很慢吗? - Hitu Bansal
是的,搜索一百万个文件需要一些时间;最好重新考虑你的选择。 - Ja͢ck
AWS提供的云搜索API怎么样? - Hitu Bansal
你可以这样做,但是你需要建立一个专门的工具来实现。事实上,我计划建立一个这样的工具。 - undefined
7个回答

22

唯一的方法是通过CloudSearch来实现,它可以使用S3作为数据源。它通过快速检索来构建索引。这应该能很好地工作,但请仔细检查定价模型,确保对您来说不会太昂贵。

另一种选择就是像Jack所说的那样 - 否则,您需要将文件从S3传输到EC2并在那里构建一个搜索应用程序。


19
2015年10月1日起,亚马逊提供了另一种基于Elastic Search的搜索服务,与Cloud Search差不多,您可以使用它从Amazon S3存储桶中流式传输数据
它将与Lambda函数一起工作,以确保发送到S3存储桶的任何新数据都会触发事件通知到该Lambda并更新ES索引。
所有步骤在Amazon文档中都有详细说明,并提供了Java和Javascript示例。
从高层次上讲,设置流式传输数据到Amazon ES需要以下步骤:
  • 创建 Amazon S3 存储桶和 Amazon ES 域。
  • 创建 Lambda 部署包。
  • 配置 Lambda 函数。
  • 授予将数据流式传输到 Amazon ES 的授权。

4
虽然不是 AWS 原生服务,但有一个名为 Mixpeek 的服务(https://mixpeek.com),可对您的 S3 文件运行文本提取,类似于 Tika、Tesseract 和 ImageAI,然后将它们放入 Lucene 索引中以使其可搜索。您可以按照以下步骤进行集成:
  1. Download the module: https://github.com/mixpeek/mixpeek-python

  2. Import the module and your API keys:

     from mixpeek import Mixpeek, S3
     from config import mixpeek_api_key, aws
    
  3. Instantiate the S3 class (which uses boto3 and requests):

     s3 = S3(
         aws_access_key_id=aws['aws_access_key_id'],
         aws_secret_access_key=aws['aws_secret_access_key'],
         region_name='us-east-2',
         mixpeek_api_key=mixpeek_api_key
     )
    
  4. Upload one or more existing S3 files:

         # upload all S3 files in bucket "demo"            
         s3.upload_all(bucket_name="demo")
    
         # upload one single file called "prescription.pdf" in bucket "demo"
         s3.upload_one(s3_file_name="prescription.pdf", bucket_name="demo")
    
  5. Now simply search using the Mixpeek module:

         # mixpeek api direct
         mix = Mixpeek(
             api_key=mixpeek_api_key
         )
         # search
         result = mix.search(query="Heartgard")
         print(result)
    
  6. Where result can be:

     [
         {
             "_id": "REDACTED",
             "api_key": "REDACTED",
             "highlights": [
                 {
                     "path": "document_str",
                     "score": 0.8759502172470093,
                     "texts": [
                         {
                             "type": "text",
                             "value": "Vetco Prescription\nVetcoClinics.com\n\nCustomer:\n\nAddress: Canine\n\nPhone: Australian Shepherd\n\nDate of Service: 2 Years 8 Months\n\nPrescription\nExpiration Date:\n\nWeight: 41.75\n\nSex: Female\n\n℞  "
                         },
                         {
                             "type": "hit",
                             "value": "Heartgard"
                         },
                         {
                             "type": "text",
                             "value": " Plus Green 26-50 lbs (Ivermectin 135 mcg/Pyrantel 114 mg)\n\nInstructions: Give one chewable tablet by mouth once monthly for protection against heartworms, and the treatment and\ncontrol of roundworms, and hookworms. "
                         }
                     ]
                 }
             ],
             "metadata": {
                 "date_inserted": "2021-10-07 03:19:23.632000",
                 "filename": "prescription.pdf"
             },
             "score": 0.13313256204128265
         }
     ] 
    

然后您解析结果。


这对我非常有效,非常感谢。 - danywigglebutt

0

你可以使用Filestash免责声明:我是作者),安装自己的实例并连接到您的S3存储桶。如果您有大量数据,请给它一些时间来索引整个内容,然后您就可以使用它了。


Filestash也可以搜索.gz文件吗? - hfranco

0
如果您有EMR,则创建一个Spark应用程序并进行搜索。我们已经这样做了。这将作为分布式搜索工作。

-1

现在有一种无服务器且更便宜的选择可用。

  1. 使用AWS Glue,您可以将txt文件转换为表格
  2. 使用AWS Athena,您可以在其上运行SQL查询。

我建议您将数据放入S3中的Parquet格式中,这将使S3上的数据大小非常小且超级快!


-1

我知道这已经很老了,但希望有人会发现我的解决方案很方便。

这是一个使用boto3的Python脚本。

def search_word (info, search_for):
    res = False
    if search_for in info:
        res = True
    elif search_for not in info:
        res = False   
    return res

import boto3
import json

aws_access_key_id='AKIAWG....'
aws_secret_access_key ='p9yrNw.....'
client = boto3.client('s3', aws_access_key_id=aws_access_key_id, aws_secret_access_key = aws_secret_access_key)
s3 = boto3.resource('s3')

bucket_name = 'my.bucket.name'
bucket_prefix='2022/05/'
search_for = 'looking@emailaddress.com'
search_results = []
search_results_keys = []

response = client.list_objects_v2(
    Bucket=bucket_name,
    Prefix=bucket_prefix
)

for i in response['Contents']:
    mini = {}
    obj = client.get_object(
        Bucket=bucket_name,
        Key=i['Key']
    )
    body = obj['Body'].read().decode("utf-8")
    key = i['Key']
    if search_word(body, search_for):
        mini = {}
        mini[key] = body
        search_results.append(mini)
        search_results_keys.append(key)

# YOU CAN EITHER PRINT THE KEY (FILE NAME/DIRECTORY), OR A MAP WHERE THE KEY IS THE FILE NAME/DIRECTORY. AND THE VALUE IS THE TXT OF THE FILE 
print(search_results)
print(search_results_keys)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接