Meilisearch v1.14 发布啦 ✨ 在我们的博客上阅读更多内容

返回首页Meilisearch 的徽标
返回文章
2022年4月5日

如何在多租户应用程序中使用 Meilisearch

在本教程中,您将学习如何从 Meilisearch 提供的租户令牌功能中获益。我们将使用 Meilisearch Javascript SDK 创建一个应用程序,该应用程序将使用租户令牌来限制基于不同用户名的对数据的访问。

Shivay Lamba
Shivay LambaMeilisearch 团队
How to use Meilisearch in your multi-tenant application

**什么是多租户?**

在软件开发中,多租户意味着多个用户(也称为租户)共享相同的计算资源,但对系统范围的数据具有不同的访问权限。在 Meilisearch 中,您可能有一个索引包含属于多个不同租户的数据。在这种情况下,您的租户必须只能搜索他们自己的文档。

您可以使用租户令牌来实现这一点。

租户令牌

租户令牌是加密数据的小包,用于证明用户可以访问特定索引。它们包含安全凭证以及关于用户被允许查看该索引中哪些文档的指令。

租户令牌的主要用例是根据用户权限强制执行限制。

用户可以使用 Meilisearch SDK自定义代码 生成租户令牌。

**租户令牌** 不需要您配置任何特定的实例选项或索引设置。它们也被设计为短期的—Meilisearch 不会存储或跟踪生成的令牌。

当使用 SDK 生成租户令牌时,您需要四个参数

  • **搜索规则**:搜索规则是一组指令,定义了将在使用特定租户令牌进行的每个查询中强制执行的搜索参数。
  • **API 密钥**:令牌可以访问与用于生成它的 API 密钥相同的索引。
  • **API 密钥 uid**:用于生成令牌的 API 密钥的 uid 允许检查所使用的 API 密钥是否有效。
  • **到期日期**(可选):租户令牌的到期日期

您可以在 文档 中阅读更多关于租户令牌负载的信息。

**要求**

  1. Node.js
  2. npm
  3. Meilisearch JavaScript SDK

**创建租户令牌**

可以使用 Meilisearch Javascript SDK 中提供的 generateTenantToken 函数创建租户令牌

这是一个使用 Meilisearch SDK 创建租户令牌的简单示例

client = new Meilisearch({
  host: "<http://localhost:7700>",
  apiKey: "masterKey",
});
// We have created a Meilisearch instance in JavaScript and we will use this to create the tenant token.

const apiKey =
  "rkDxFUHd02193e120218f72cc51a9db62729fdb4003e271f960d1631b54f3426fa8b2595";
const apiKeyUid = "85c3c2f9-bdd6-41f1-abd8-11fcf80e0f76";
const expiresAt = new Date("2025-01-01");
// Now we have declared the API Key, its uid, as well as the expiration date for the token.

searchRules = {
  "*": {
    filter: "user_id = 1",
  },
};
// Here we have defined the search rules that will apply restrictions on the search results.

tenantToken = client.generateTenantToken(apiKeyUid, searchRules, {
  expiresAt: expiresAt,
  apiKey: apiKey,
});
// Now the generateTenantToken function will create a tenant token and Meilisearch can validate this token with the apiKey.

当 Meilisearch 收到带有租户令牌的搜索查询时,它会解码它并将搜索规则应用于搜索请求。

应用场景

假设我们在一个 Meilisearch 实例中有一个医疗记录系统,索引名为 patient_medical_record。此索引包含患者列表及其详细信息。我们可以使用租户令牌来限制对这些数据的访问。

示例数据集

[
  {
    "patient": "John",
    "description": "John is in room number 2 and is suffering from Covid",
    "roomNumber": 1,
    "isDoctorAppointed": true
  },
  {
    "patient": "Zia",
    "description": "Zia is in room number 3 and is suffering from Dengue",
    "roomNumber": 2,
    "isDoctorAppointed": true
  },
  {
    "patient": "Kevin",
    "description": "Kevin is in room number 4 and is suffering from Typhoid",
    "roomNumber": 3,
    "isDoctorAppointed": false
  }
]

在上面的数据集中,我们有三位患者:John、Zia 和 Kevin。目标是限制 Zia 访问 Kevin 和 John 的数据。为了实现这一点,我们需要为她创建一个带有搜索规则集的租户令牌

对于这种情况,搜索规则可以指定为

"searchRules": {
      "patient_medical_record": {
          "filter": "patient = Zia"
      }
  }

Zia 的租户令牌将在搜索请求时应用,这将返回

[
  {
    "patient": "Zia",
    "description": "Zia is in room number 3 and is suffering from Dengue",
    "roomNumber": 2,
    "isDoctorAppointed": true
  }
]

这是一个简单的用例,但我们可以修改规则以满足更复杂的需求。

**在您的应用程序中集成多租户功能**

我们将使用上面的示例创建一个应用程序,用于显示 Meilisearch 索引中的患者。然后,我们将使用多租户来限制对这些数据的访问。

  1. 下载应用程序

    从 Github 上的 Meilisearch 教程仓库克隆演示应用程序的样板代码。

    使用以下命令

git clone https://github.com/meilisearch/tutorials

样板代码位于 src/tenant-token-tutorial 目录中。

cd src/tenant-token-tutorial

此代码包含一个用 React.js 构建的前端应用程序和一个用 Express.js/Node.js 构建的后端服务器。

  1. 启动 Meilisearch

    有多种方法可以 下载并运行 Meilisearch 实例。运行 Meilisearch 实例的最简单方法是使用 Meilisearch Cloud,它提供 14 天免费试用,无需信用卡。Meilisearch 是开源的,在本演示中,我们将使用 Docker 在本地运行它

   docker pull getmeili/meilisearch:v1.0


   docker run -it --rm 
       -p 7700:7700 
       -e MEILI_MASTER_KEY='masterKey'
       -v $(pwd)/meili_data:/meili_data 
       getmeili/meilisearch:v1.0 
       meilisearch --env="development"

启动 Meilisearch 时,不要忘记定义一个 主密钥,如上所示。它将创建生成租户令牌所需的 API 密钥。

Meilisearch 实例将在 IP 地址 http://localhost:7700 上运行。

  1. 向 Meilisearch 添加数据

    在基本目录的 seed 文件夹中有一个 data.json 文件,其中包含 10 位患有多种疾病的患者列表,共 100 条记录,每条记录都有房间号和一些患者详细信息。我们将把这些信息输入到 Meilisearch 中。

    将终端目录更改为 seed 文件夹,并使用以下命令将给定的数据添加到 Meilisearch 实例中

npm install     #  This command will install node dependencies

npm start         # This command will add all the data from data.json to Meilisearch

  1. 启动前端服务器

    导航到 frontend 文件夹,并安装所有应用程序依赖项和 Meilisearch Javascript SDK

npm install                # To install all the react application dependency

npm install meilisearch    # To install the Meilisearch SDK

安装项目的所有依赖项可能需要一段时间。

让我们使用以下命令启动并运行前端 React 服务器

npm start

应用程序将在 IP 地址 http://localhost:3000 上运行。

drawing

  1. 添加创建租户令牌的功能

    导航到 backend 文件夹,并使用以下命令安装所有依赖项

npm install

backend 文件夹中,打开 index.js 文件。它包含 API 的路由和逻辑。

已经定义了一个用于生成 租户令牌 的端点

app.get("/create-tenant-token", async (req, res) => {
  const { value: patientName } = req.query;

  /* Add functionality to create Tenant token */
});

现在,我们将在函数中注释下方添加功能。

我们需要 API 密钥、搜索规则和到期日期来生成租户令牌。

API 密钥可以从 Javascript SDK 中的 getKeys 方法获得。getKeys 方法返回 API 密钥列表,我们可以从中选择一个用于租户令牌生成过程。为此,请将以下代码添加到上述 API 方法中

const { results } = await client.getKeys();
const apiKey = results.filter(
  (res) => res.name === "Default Search API Key"
)[0].key;
const apiKeyUid = results.filter(
  (res) => res.name === "Default Search API Key"
)[0].uid;

我们还可以使用 createKey 函数生成新的 API 密钥。

您可以在 Meilisearch 文档 中阅读更多关于 API 密钥的信息。

通过指定搜索规则,我们现在可以生成负载。使用以下代码定义负载

const payload = {
  patient_medical_record: {
    filter: `patient = ${patientName}`,
  },
};

如果我们需要令牌在一年后过期,我们可以在创建令牌时设置到期日期,如下所示。

const expiresAt = new Date(
  new Date().setFullYear(new Date().getFullYear() + 1)
);

要生成令牌,我们现在可以使用 Meilisearch Javascript SDK 中的 generateTenantToken 函数,并使用 res.json() 函数返回生成的令牌。

const tenantToken = client.generateTenantToken(apiKeyUid, payload, {
  apiKey,
  expiresAt,
});

return res.json({ token: tenantToken });

这就是端点应该如何实现的

app.get("/create-tenant-token", async (req, res) => {
  const { value: patientName } = req.query;

  /* Add functionality to create Tenant token */
  const { results } = await client.getKeys();
  const apiKey = results.filter(
    (res) => res.name === "Default Search API Key"
  )[0].key;
  const apiKeyUid = results.filter(
    (res) => res.name === "Default Search API Key"
  )[0].uid;

  const payload = {
    patient_medical_record: {
      filter: `patient = ${patientName}`,
    },
  };

  const expiresAt = new Date(
    new Date().setFullYear(new Date().getFullYear() + 1)
  );

  const tenantToken = client.generateTenantToken(apiKeyUid, payload, {
    apiKey,
    expiresAt,
  });

  return res.json({ token: tenantToken });
});

前端请求的端点将如下所示

http://localhost:5001/create-tenant-token?value=John

使用 API 中的值 John 创建包含搜索规则的负载。

让我们使用 npm start 命令启动 express API 服务器。服务器将在 http://localhost:5001 上运行。

  1. 将您的 API 与前端代码连接

    在文本框中输入患者姓名。提交输入表单后,API 调用将发送到后端,后端应返回租户令牌。当我们需要关于特定患者的数据时,我们可以将此令牌传递给 Meilisearch 实例。

    现在必须配置前端代码以从服务器请求租户令牌。我们将使用 axios 库 从我们开发的 /create-tenant-token API 获取令牌,并将患者姓名传递到 API 的参数中。

    打开 /src/utils 文件夹中的 index.js 文件,并查找 getTenantToken 函数。此函数向服务器发出请求并接收返回的租户令牌。

    将以下代码添加到 getTenantToken 方法

export const getTenantToken = async (patientName) => {
  const response = await axios({
    url: `${apiHost}/create-tenant-token`,
    method: "GET",
    params: {
      value: patientName,
    },
  });

  return response.data.token;
};
  1. 测试已实现的功能

    让我们测试实现;首先单击 **创建租户令牌** 按钮。

    drawing

    在给定的文本框中输入名称 Kevin,然后单击 **创建租户令牌 按钮**。这将生成租户令牌。

    meili-create-token

    Meilisearch 将根据患者提供的租户令牌获取数据,在此过程中充当身份验证器。

结论

我们已经根据患者姓名限制了对医疗记录的访问。使用 Meilisearch 的多租户功能,我们能够轻松地执行所有这些操作。这是一个想到的非常基本的用例场景。该功能可以根据您的需要变得复杂。例如,我们可以在电子银行应用程序中实现多租户,其中中央机构是银行,客户是租户,可以访问不同的银行帐户。

如果您有任何问题,请在 Discord 上加入我们。有关 Meilisearch 的更多信息,请查看我们的 Github 仓库 和我们的官方 文档

Meilisearch indexes embeddings 7x faster with binary quantization

Meilisearch 通过二值量化将嵌入向量索引速度提升 7 倍

通过使用向量存储 Arroy 实现二值量化,在保持搜索相关性和效率的同时,大幅减少了大型嵌入向量的磁盘空间使用量和索引时间。

Tamo
Tamo2024年11月29日
How to add AI-powered search to a React app

如何在 React 应用中添加 AI 驱动的搜索功能

使用 Meilisearch 的 AI 驱动的搜索功能构建一个 React 电影搜索和推荐应用程序。

Carolina Ferreira
Carolina Ferreira2024年9月24日
Meilisearch is too slow

Meilisearch 速度太慢

在这篇博文中,我们将探讨 Meilisearch 文档索引器所需的增强功能。我们将讨论当前的索引引擎、其缺点以及优化性能的新技术。

Clément Renault
Clément Renault2024年8月20日