# 使用 DynamoDB 和 Typesense 实现全文模糊搜索
本教程将展示如何将 DynamoDB 表中的数据导入 Typesense,然后使用 Typesense 进行支持容错、过滤、分面等功能的全文搜索。
总体而言,我们将设置一个 Lambda 函数,通过 DynamoDB 流 (opens new window)监听变更事件,并将数据写入 Typesense。
# 第一步:创建 Typesense 集群
在 Typesense Cloud (opens new window) 上注册账户,创建一个集群并获取 Endpoint URL、端口号和 API 密钥。
本教程使用 Typesense Cloud,因为我们需要一个公开的 Typesense 端点供 Lambda 函数写入数据。
你也可以选择在自己的服务器或云服务提供商上自托管 Typesense。有关自托管 Typesense 的更多详情,请参阅 Typesense 安装指南。
# 第二步:创建 DynamoDB 表
创建一个 DynamoDB 表,自定义表名和分区键(推荐使用 "id")。创建表后,你需要在 AWS 控制台的概览部分启用流功能。
你也可以使用 AWS CLI 完成此操作:
aws dynamodb create-table \
--table-name YourTableName \
--attribute-definitions AttributeName=id,AttributeType=N \
--key-schema AttributeName=id,KeyType=HASH \
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES
# 步骤 3:创建 Lambda 执行角色
现在我们来创建一个 "Lambda 执行角色",即为您的函数授予访问所需资源的权限。
前往 AWS 控制台的 IAM 角色部分,创建一个新的 IAM 角色,并赋予以下三个主要权限:
- AmazonDynamoDBFullAccess
- AmazonDynamoDBFullAccesswithDataPipeline
- AWSLambdaBasicExecutionRole
WARNING
这些 IAM 角色权限仅为本指南的示例。在生产环境部署前,请参考 IAM 文档,仅授予您的特定用例所需的最小权限。
您也可以使用 AWS CLI 完成此操作:
创建一个名为 trust-relationship.json
的文件,内容如下:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
然后执行以下命令:
aws iam create-role --role-name YourLambdaRole \
--path "/service-role/" \
--assume-role-policy-document file://trust-relationship.json
接下来创建 role-policy.json
文件,内容如下(替换 accountID
和 region
):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:region:accountID:function:typesense-indexing*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:region:accountID:*"
},
{
"Effect": "Allow",
"Action": [
"dynamodb:DescribeStream",
"dynamodb:GetRecords",
"dynamodb:GetShardIterator",
"dynamodb:ListStreams"
],
"Resource": "arn:aws:dynamodb:region:accountID:table/typesense/stream/*"
},
]
}
该策略包含三个声明,允许 TypesenseLambdaRole 执行以下操作:
- 运行名为
typesense-indexing
的 Lambda 函数(我们将在本教程稍后创建此函数) - 访问 Amazon CloudWatch Logs(Lambda 函数在运行时会将诊断信息写入 CloudWatch Logs)
- 从
typesense
的 DynamoDB 流中读取数据
现在,我们将上述角色附加到已创建的 IAM 执行角色上:
aws iam put-role-policy --role-name YourLambdaRole \
--policy-name TypesenseLambdaRolePolicy \
--policy-document file://role-policy.json
# 步骤4:创建Lambda函数
前往AWS控制台的Lambda部分,使用之前创建的执行角色创建一个新的Lambda函数。详细说明请参阅AWS Lambda执行角色文档 (opens new window)
以下是DynamoDB调用我们的Lambda函数时可能传递的事件示例:
{
"Records": [
{
"eventID": "2",
"eventVersion": "1.0",
"dynamodb": {
"OldImage": {
// 现有值
},
"SequenceNumber": "222",
"Keys": {
// 分区键和排序键
},
"SizeBytes": 59,
"NewImage": {
// 新值
},
"awsRegion": "us-east-2",
"eventName": "MODIFY", // 可能是'INSERT'、'MODIFY'或'DELETE'
"eventSourceARN": "<AWS-ARN>",
"eventSource": "aws:dynamodb"
},
}
]
}
现在将以下代码添加到我们的Lambda函数中。我们使用Python作为示例,但你也可以使用Node、Ruby或AWS Lambda支持的任何语言。
def lambda_handler(event, context):
client = typesense.Client({
'nodes': [{
'host': '<Endpoint URL>',
'port': '<Port Number>',
'protocol': 'https',
}],
'api_key': '<API Key>',
'connection_timeout_seconds': 2
})
processed = 0
for record in event['Records']:
ddb_record = record['dynamodb']
if record['eventName'] == 'REMOVE':
res = client.collections['<collection-name>'].documents[str(ddb_record['OldImage']['id']['N'])].delete()
else:
document = ddb_record['NewImage'] # 在此处格式化你的文档,然后使用upsert函数建立索引
res = client.collections['<collection-name>'].upsert(document)
print(res)
processed = processed + 1
print('Successfully processed {} records'.format(processed))
return processed
有关创建集合和文档的所有可用参数的详细信息,请参阅Typesense API文档。
TIP
使用pip install <dependency-name> -t .
安装所有依赖项。这将在当前目录中安装函数所需的所有依赖项,这正是Lambda所期望的。
完成后,将当前目录压缩并通过AWS控制台上传到你的Lambda函数。
你也可以使用AWS CLI完成此操作:
获取你创建的执行角色的ARN:
aws iam get-role --role-name YourLambdaRole
在输出中查找ARN:
... "Arn": "arn:aws:iam::region:role/service-role/YourLambdaRole" ...
现在创建Lambda函数:
aws lambda create-function \ --region us-east-2 \ --function-name YourLambdaFunction \ --zip-file fileb://YourZipFile.zip \ --role YourRoleARN \ --handler lambda_function.lambda_handler \ --timeout 5 \ --runtime python3.7
# 步骤5:设置触发器
现在,在AWS控制台中导航到您的DynamoDB表,访问Triggers(触发器)部分,并将现有的Lambda函数添加到该表中。
您也可以使用AWS CLI完成此操作:
- 获取DynamoDB表的ARN注意流ARN:
aws dynamodb describe-table --table-name YourTableName
... "LatestStreamArn": "arn:aws:dynamodb:`region`:`accountID`:table/`table-name`/stream/`timestamp`" ...
- 现在,将此ARN添加到Lambda:
aws lambda create-event-source-mapping \ --region us-east-1 \ --function-name YourLambdaFunction \ --event-source YourStreamARN \ --batch-size 1 \ --starting-position TRIM_HORIZON
TIP
在高流量环境中处理大量变更时,我们强烈建议您将写入操作批量处理到Typesense中。 您可以使用类似Kinesis的服务暂存DynamoDB事件,然后使用import endpoint将变更批量写入Typesense。
大功告成!现在您在DynamoDB表中创建、更新或删除的任何数据都将自动索引到您的Typesense集群中。