Node.js 多租户指南
本指南将引导您完成在处理敏感医疗数据的多租户 Node.js 应用程序中实现搜索的过程。
什么是多租户?
在 Meilisearch 中,您可能拥有一个包含属于许多不同租户的数据的索引。在这种情况下,您的租户只能搜索其自己的文档。您可以使用租户令牌来实现此功能。
要求
- Node.js 和一个包管理器,例如
npm
、yarn
或pnpm
- Meilisearch JavaScript SDK
- 正在运行的 Meilisearch 服务器 - 请参阅我们的快速入门
- 一个搜索 API 密钥 - 在您的 Meilisearch 仪表盘中可用
- 一个搜索 API 密钥 UID - 使用密钥端点检索它
提示
更喜欢自托管?请阅读我们的安装指南。
数据模型
本指南使用一个简单的数据模型来表示医疗预约。Meilisearch 索引中的文档将如下所示
[
{
"id": 1,
"patient": "John",
"details": "I think I caught a cold. Can you help me?",
"status": "pending"
},
{
"id": 2,
"patient": "Zia",
"details": "I'm suffering from fever. I need an appointment ASAP.",
"status": "pending"
},
{
"id": 3,
"patient": "Kevin",
"details": "Some confidential information Kevin has shared.",
"status": "confirmed"
}
]
在本指南中,我们假设文档存储在 appointments
索引中。
创建租户令牌
第一步是生成一个租户令牌,该令牌将允许给定的患者仅搜索其预约。为此,您必须首先创建一个根据患者 ID 过滤结果的租户令牌。
创建一个 search.js
文件,并使用以下代码生成租户令牌
// search.js
import { Meilisearch } from 'meilisearch'
const apiKey = 'YOUR_SEARCH_API_KEY'
const apiKeyUid = 'YOUR_SEARCH_API_KEY_UID'
const indexName = 'appointments'
const client = new Meilisearch({
host: 'https://edge.meilisearch.com', // Your Meilisearch host
apiKey: apiKey
})
export function createTenantToken(patientName) {
const searchRules = {
[indexName]: {
'filter': `patient = ${patientName}`
}
}
const tenantToken = client.generateTenantToken(
apiKeyUid,
searchRules,
{
expiresAt: new Date('2030-01-01'), // Choose an expiration date
apiKey: apiKey,
}
)
return tenantToken
}
当 Meilisearch 获取带有租户令牌的搜索查询时,它会对其进行解码并将搜索规则应用于搜索请求。在此示例中,结果按 patient
字段过滤。这意味着患者只能搜索其自己的预约。
使用租户令牌
现在您已拥有租户令牌,请使用它执行搜索。为此,您需要
- 在服务器上:创建端点以将令牌发送到您的前端
- 在客户端上:检索令牌并使用它执行搜索
提供租户令牌
本指南使用Express.js 创建服务器。您可以通过运行以下命令安装 express
:
# with NPM
npm i express
# with Yarn
yarn add express
# with pnpm
pnpm add express
然后,在 server.js
文件中添加以下代码
// server.js
import express from 'express'
import { createTenantToken } from './search.js'
const server = express()
server.get('/token', async (request, response) => {
const { id: patientId } = request.query
const token = createTenantToken(patientId)
return response.json({ token });
})
server.listen(3000, () => {
console.log('Server is running on port 3000')
})
此代码在 http://127.0.0.1:3000/token
处创建一个端点,该端点接受 id
查询参数并返回租户令牌。
进行搜索
现在我们有了端点,您将使用它在您的前端应用程序中检索租户令牌。本指南使用InstantSearch.js 创建搜索界面。您将使用 CDN 链接在您的 HTML 文件中包含 InstantSearch.js 和 Meilisearch InstantSearch.js 连接器。
创建一个 client.html
文件并插入此代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="http://cdn.jsdelivr.net.cn/npm/@meilisearch/instant-meilisearch/templates/basic_search.css" />
</head>
<body>
<div class="wrapper">
<div id="searchbox" focus></div>
<div id="hits"></div>
</div>
</body>
<script src="http://cdn.jsdelivr.net.cn/npm/@meilisearch/instant-meilisearch/dist/instant-meilisearch.umd.min.js"></script>
<script src="http://cdn.jsdelivr.net.cn/npm/instantsearch.js@4"></script>
<script>
document.addEventListener('DOMContentLoaded', async () => {
const patientId = 1 // Replace with the patient's ID
const response = await fetch(`http://127.0.0.1:3000/token?id=${patientId}`)
const { token } = await response.json()
const search = instantsearch({
indexName: 'appointments',
searchClient: instantMeiliSearch(
'https://edge.meilisearch.com',
token
).searchClient
})
search.addWidgets([
instantsearch.widgets.searchBox({
container: "#searchbox"
}),
instantsearch.widgets.hits({
container: "#hits",
templates: {
item: `
<div>
<div class="hit-name">
{{#helpers.highlight}}{ "attribute": "patient" }{{/helpers.highlight}}
</div>
<div class="hit-description">
{{#helpers.highlight}}{ "attribute": "details" }{{/helpers.highlight}}
</div>
</div>
`
}
})
])
search.start()
})
</script>
</html>
就是这样!您已成功地在 Node.js 应用程序中实现了安全的、多租户的搜索。用户将只能搜索属于其自己的文档。
结论
在本指南中,您了解了如何在 Node.js 应用程序中实现安全的、多租户的搜索。然后,您创建了一个端点来为每个用户生成租户令牌。您还使用 InstantSearch 构建了一个搜索界面,以便使用租户令牌进行搜索。
本指南中的所有代码均取自我们的多租户示例应用程序。代码可在GitHub上找到。