如何在 Ubuntu 22.04 上使用 InstantSearch 运行 Meilisearch 前端

介绍

Meilisearch是一个开源,独立的搜索引擎,用高性能的 Rust编程语言编写,与其他流行的搜索引擎相比,Meilisearch专注于保持部署简单 - 它提供了模糊的匹配和无计划的索引功能,并由单个命令行二进制进行管理。它包括自己的Web前端用于演示目的,并可与InstantSearch库集成,以便更复杂的Web部署。

在本系列中的前一本教程中(https://andsky.com/tech/tutorials/how-to-deploy-and-configure-meilisearch-on-ubuntu-22-04),你在Ubuntu 22.04 服务器上安装并配置了 Meilisearch. 你还尝试了加载数据和查询 Meilisearch 使用其在开发模式中包含的非生产式网页前端。

前提条件

要遵循本教程,您将需要:

步骤 1 – 获取 Meilisearch API 密钥并启用生产模式

本系列的上一本教程中,您配置了 Meilisearch 以使用环境变量运行docker-compose

使用cd命令返回您的meilisearch-docker目录,然后使用nano或您最喜欢的文本编辑器,打开meilisearch.env配置文件:

1cd ~/meilisearch-docker
2nano meilisearch.env

将一个行添加到文件的末尾,其中包含 MEILI_ENV="production". 启用此设置将禁用内置的搜索预览接口,并优化一些内部日志参数:

1[label ~meilisearch-docker/meilisearch.env]
2MEILI_MASTER_KEY="secret_key"
3MEILI_ENV="production"

保存并关闭文件,按Ctrl+X,然后在提示时,Y,然后ENTER

1docker compose down
2docker compose up --detach

通过使用docker-compose ps来验证它是否成功重新启动:

1docker compose ps
1[secondary_label Output]
2NAME              	COMMAND              	SERVICE         	STATUS          	PORTS
3sammy-meilisearch-1   "tini -- /bin/sh -c …"   meilisearch     	running         	127.0.0.1:7700->7700/tcp

在之前的教程中,您测试了 Meilisearch 使用本地索引,然后创建了一个新的docker-compose.yml配置,以确保您的 Meilisearch 实例上载了一些示例数据,重新运行以下curl -X POST命令。

<$>[注] 注: Meilisearch 项目提供了从 TMDB,电影数据库中摘取的样本 JSON 格式数据集,如果您还没有,请使用wget命令从 `docs.meilisearch.com’下载数据:

1wget https://docs.meilisearch.com/movies.json

美元

这一次,将您的secret_key列入Authorization: Bearer secret_key HTTP 标题的一部分。

第一個命令將「movies.json」檔案載入 Meilisearch:

1curl -X POST 'http://localhost:7700/indexes/movies/documents'   -H 'Content-Type: application/json' -H 'Authorization: Bearer secret_key'  --data-binary @movies.json

第二个命令更新您的 Meilisearch 配置,以允许按类型和发布日期过滤,并按发布日期排序。

1curl -X POST 'http://localhost:7700/indexes/movies/settings'   -H 'Content-Type: application/json' -H 'Authorization: Bearer secret_key'  --data-binary '{ "filterableAttributes": [ "genres", "release_date" ], "sortableAttributes": [ "release_date" ] }'

最后,在您继续到下一步之前,请获得具有更有限权限的只读身份验证密钥. 您将使用此密钥与前端界面进行搜索查询,因此它只需要只读权限。

1curl -X GET 'http://localhost:7700/keys' -H 'Authorization: Bearer secret_key'
 1[secondary_label Output]
 2{
 3  "results": [
 4    {
 5      "description": "Default Search API Key (Use it to search from the frontend)",
 6      "key": "SwlztWf7e71932abed4ecafa6cb32ec06446c3117bd49f5415f822f4f126a29c528a7313",
 7      "actions": [
 8        "search"
 9      ],
10      "indexes": [
11        "*"
12      ],
13      "expiresAt": null,
14      "createdAt": "2022-03-10T22:02:28Z",
15      "updatedAt": "2022-03-10T22:02:28Z"
16    },
17    {
18      "description": "Default Admin API Key (Use it for all other operations. Caution! Do not use it on a public frontend)",
19      "key": "mOTFYUKeea1169e07be6e89de180de4809be5a91be667af364e45a046850bbabeef669a5",
20      "actions": [
21        "*"
22      ],
23      "indexes": [
24        "*"
25      ],
26      "expiresAt": null,
27      "createdAt": "2022-03-10T22:02:28Z",
28      "updatedAt": "2022-03-10T22:02:28Z"
29    }
30  ]
31}

请记住默认搜索 API 密钥。您将使用它代替default_search_api_key的位置,以在下一步配置您的前端。您也可以通过遵循 身份验证文档来创建或删除 Meilisearch API 密钥。

现在 Meilisearch 索引在生产模式中运行,您可以使用 Nginx 配置访问您的 Meilisearch 服务器。

步骤 2 — 安装 Nginx 并配置 HTTPS 上的反向代理

将 Nginx 等 Web 服务器放在 Meilisearch 前面可以提高性能,并使通过 HTTPS 更简单地保护网站。 您将安装 Nginx 并将其配置为 reverse proxy请求到 Meilisearch,这意味着它将负责处理用户对 Meilisearch 的请求并再次返回。

如果你正在使用ufw防火墙,你应该在这个时候对你的防火墙配置做出一些更改,以允许访问默认的HTTP/HTTPS端口,80和443.ufw有一个名为Nginx Full的库存配置,可以访问这两个端口:

1sudo ufw allow "Nginx Full"

现在,更新您的包列表,然后使用apt安装 Nginx:

1sudo apt install nginx

Nginx 允许您在名为sites-available/的子目录中添加每个站点的配置,使用nano或您最喜欢的文本编辑器,在/etc/nginx/sites-available/meili创建一个新的 Nginx 配置:

1sudo nano /etc/nginx/sites-available/meili

将以下内容粘贴到新的配置文件中,确保用您的域名更换your_domain

 1[label /etc/nginx/sites-available/meili]
 2server {
 3    listen 80 default_server;
 4    listen [::]:80 default_server;
 5    server_name your_domain;
 6    root /var/www/html;
 7
 8    access_log /var/log/nginx/meilisearch.access.log;
 9    error_log /var/log/nginx/meilisearch.error.log;
10
11    location / {
12        try_files $uri $uri/ index.html;
13    }
14
15    location /indexes/movies/search {
16        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
17        proxy_set_header X-Real-IP $remote_addr;
18        proxy_set_header X-Forwarded-Host $host;
19        proxy_set_header X-Forwarded-Proto https;
20        proxy_pass http://127.0.0.1:7700;
21    }
22
23    location /dev {
24       proxy_set_header Connection "";
25       proxy_set_header Host $http_host;
26       proxy_set_header X-Real-IP $remote_addr;
27       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
28       proxy_set_header X-Forwarded-Proto $scheme;
29       proxy_set_header X-Frame-Options SAMEORIGIN;
30       proxy_http_version 1.1;
31       proxy_pass http://127.0.0.1:1234;
32    }
33}

这是一个最小的反向代理配置,它会听取默认 HTTP 端口上的外部请求,即 `80。

*位置/块将从 Nginx 的默认/var/www/html目录中提供索引页面 *位置/indexes/movies/search块将请求转发到 Meilisearch 后端,在端口7700上运行 *位置/dev/块将用于在本教程中稍后将请求转发到您的 InstantSearch 前端的开发版本

<$>[注] 注: 如果您想将另一个索引添加到这个 Meilisearch 后端,您需要为这个 Nginx 配置添加另一个块,例如包含相同内容的位置 /indexes/books/search {},以便拦截正确的 URL。

不要忘了用您的域名替换 your_domain,因为这将是需要在端口443上添加HTTPS支持的。

接下来,您需要激活这个新配置。Nginx的惯例是创建符号链接(如快捷键)从可用网站中的文件到另一个名为可用网站的文件夹,当您决定激活或禁用它们时。

1sudo ln -s /etc/nginx/sites-available/meili /etc/nginx/sites-enabled/meili

默认情况下, Nginx 包含另一个配置文件在 /etc/nginx/sites-available/default,链接到 /etc/nginx/sites-enabled/default,这也是其默认索引页面。

1sudo rm /etc/nginx/sites-enabled/default

现在你可以继续启用 HTTPS. 要做到这一点,你将从 Let’s Encrypt 项目中安装certbot。 Let’s Encrypt 更喜欢通过一个snap包来分发 Certbot,所以你可以使用snap install命令,默认情况下在 Ubuntu 22.04 上可用:

1sudo snap install --classic certbot
1[secondary_label Output]
2certbot 1.25.0 from Certbot Project (certbot-eff✓) installed

接下来,在--nginx模式下运行certbot。使用-d旗,指定您的域名:

1sudo certbot --nginx -d your-domain

您将被要求同意 Let's Encrypt 服务条款,并输入电子邮件地址。

之后,您将被问及是否要将所有HTTP流量重定向到HTTPS。

之后,Let’s Encrypt 将确认您的请求,Certbot 将下载您的证书:

 1[secondary_label Output]
 2 3Successfully deployed certificate for your-domain to /etc/nginx/sites-enabled/meili
 4Congratulations! You have successfully enabled HTTPS on https://your-domain
 5
 6- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 7If you like Certbot, please consider supporting our work by:
 8 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 9 * Donating to EFF:                    https://eff.org/donate-le
10- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Certbot 将自动重新加载 Nginx 与新的配置和证书。

一旦您在防火墙中打开一个端口并设置了反向代理和证书,您应该能够通过 HTTPS 远程查询 Meilisearch. 您可以通过使用与以前相同的语法使用 cURL 来测试这一点 - 一个 HTTPS URL 将默认为端口 443,而certbot将自动添加到您的 Nginx 配置:

1[environment local]
2curl \
3  -X POST 'https://your_domain/indexes/movies/search' \
4  -H 'Content-Type: application/json' \
5  -H 'Authorization: Bearer secret_key' \
6  --data-binary '{ "q": "saint" }'

现在您的 HTTPS 配置已经到位,您已经准备好开始构建前端搜索应用程序。

步骤 3 — 在新 Node.js 项目中安装 Instant-mellisearch

在此步骤中,您将使用 instant-mellisearch创建一个新的 Node.js 项目,该项目是 Meilisearch 的 InstantSearch 前端。

使用mkdir为该项目创建一个新目录,并使用cd进行更改:

1mkdir ~/my-instant-meili
2cd ~/my-instant-meili

接下来,使用npm init来初始化 Node.js 项目:

1npm init

你可以尽可能地描述在这里,假设你最终可以将这个项目发布到像Github这样的存储库或到npm包注册表。

 1[secondary_label Output]
 2This utility will walk you through creating a package.json file.
 3It only covers the most common items, and tries to guess sensible defaults.
 4
 5See `npm help json` for definitive documentation on these fields
 6and exactly what they do.
 7
 8Use `npm install <pkg>` afterwards to install a package and
 9save it as a dependency in the package.json file.
10
11Press ^C at any time to quit.
12package name: (instant) my-instant-meili
13version: (1.0.0)
14description:
15entry point: (index.js) index.html
16test command:
17git repository:
18keywords:
19author:
20license: (ISC)

在仔细查看该文件之前,您可以使用npm来安装该项目的一些依赖性,这些依赖性将添加到package.json并安装到node_modules子目录中:

1npm i @meilisearch/instant-meilisearch @babel/core parcel-bundler

现在,使用nano或您最喜欢的文本编辑器,打开package.json:

1nano package.json

你的文件应该看起来像这样,反映你在npm init过程中所做的更改和你刚刚安装的依赖性。你要做的更改是脚本块。用下面的开始构建命令替换默认条目,这将允许你使用 javascript的工具来服务你的新应用:

 1[label package.json]
 2{
 3  "name": "my-instant-meili",
 4  "version": "1.0.0",
 5  "description": "",
 6  "main": "index.html",
 7  "scripts": {
 8    "start": "parcel index.html --global instantMeiliSearch --public-url /dev",
 9    "build": "parcel build --global instantMeiliSearch index.html"
10  },
11  "dependencies": {
12    "@babel/core": "7.14.0",
13    "@meilisearch/instant-meilisearch": "0.6.0",
14    "parcel-bundler": "1.12.5"
15  },
16  "devDependencies": {
17    "@babel/core": "7.2.0",
18    "parcel-bundler": "^1.6.1"
19  },
20  "keywords": []
21}

保存并关闭文件. 如果您正在使用nano,请按Ctrl+X,然后在提示时按Y,然后按ENTER

接下来,您将为此应用提供第一个 HTML、CSS 和 javascript 组件. 您可以将下面的示例粘贴到新的文件中,而不会进行更改,因为它们提供了可用的基线配置。

首先,打开index.html,然后添加以下HTML:

1nano index.html
 1[label index.html]
 2<!DOCTYPE html>
 3<html lang="en">
 4  <head>
 5    <meta charset="utf-8" />
 6    <meta
 7      name="viewport"
 8      content="width=device-width, initial-scale=1, shrink-to-fit=no"
 9    />
10    <meta name="theme-color" content="#000000" />
11    <link
12      rel="stylesheet"
13      href="https://cdn.jsdelivr.net/npm/instantsearch.css@7/themes/algolia-min.css"
14    />
15    <link rel="stylesheet" href="./index.css" />
16
17    <title>MeiliSearch + InstantSearch</title>
18  </head>
19  <body>
20    <div class="ais-InstantSearch">
21      <h1>MeiliSearch + InstantSearch.js</h1>
22      <h2>Search Movies!</h2>
23
24      <div class="right-panel">
25        <div id="searchbox" class="ais-SearchBox"></div>
26        <div id="hits"></div>
27        <div id="pagination"></div>
28      </div>
29    </div>
30    <script src="https://cdn.jsdelivr.net/npm/instantsearch.js@4"></script>
31    <script src="./app.js"></script>
32  </body>
33</html>

index.html文件加载了远程和本地资产 - 如上所示,您还需要创建index.cssapp.js

1nano index.css

将以下内容添加到文件中:

 1[label index.css]
 2body,
 3h1 {
 4  margin: 0;
 5  padding: 0;
 6}
 7
 8body {
 9  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
10    Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
11  padding: 1em;
12}
13
14.ais-ClearRefinements {
15  margin: 1em 0;
16}
17
18.ais-SearchBox {
19  margin: 1em 0;
20}
21
22.ais-Pagination {
23  margin-top: 1em;
24}
25
26.left-panel {
27  float: left;
28  width: 200px;
29}
30
31.right-panel {
32  margin-left: 210px;
33}
34
35.ais-InstantSearch {
36  max-width: 960px;
37  overflow: hidden;
38  margin: 0 auto;
39}
40
41.ais-Hits-item {
42  margin-bottom: 1em;
43  width: calc(50% - 1rem);
44}
45
46.ais-Hits-item img {
47  margin-right: 1em;
48  width: 100%;
49  height: 100%;
50  margin-bottom: 0.5em;
51}
52
53.hit-name {
54  margin-bottom: 0.5em;
55}
56
57.hit-description {
58  font-size: 90%;
59  margin-bottom: 0.5em;
60  color: grey;
61}
62
63.hit-info {
64  font-size: 90%;
65}

您可以根据需要更改 CSS 参数,或者保留默认值。 保存并关闭该文件,然后最终创建app.js:

1nano app.js
 1[label app.js]
 2import { instantMeiliSearch } from "@meilisearch/instant-meilisearch";
 3
 4const search = instantsearch({
 5  indexName: 'movies',
 6  searchClient: instantMeiliSearch(
 7    "https://your domain",
 8    "default_search_api_key"
 9  ),
10})
11
12search.addWidgets([
13  instantsearch.widgets.searchBox({
14    container: "#searchbox"
15  }),
16  instantsearch.widgets.configure({
17    hitsPerPage: 6,
18    snippetEllipsisText: "...",
19    attributesToSnippet: ["description:50"]
20  }),
21  instantsearch.widgets.hits({
22    container: "#hits",
23    templates: {
24      item: `
25        <div>
26          <div class="hit-name">
27            {{#helpers.highlight}}{ "attribute": "title" }{{/helpers.highlight}}
28          </div>
29          <img src="{{poster}}" align="left" />
30          <div class="hit-description">
31            {{#helpers.snippet}}{ "attribute": "overview" }{{/helpers.snippet}}
32          </div>
33          <div class="hit-info">Genre: {{genres}}</div>
34        </div>
35      `
36    }
37  }),
38  instantsearch.widgets.pagination({
39    container: "#pagination"
40  })
41]);
42
43search.start();

此文件包含您的 Meilisearch 索引的连接详细信息. 确保indexName,IP 地址和身份验证密钥都匹配您用curl测试的值。

<$>[注] :本文件底部的模板块处理如何显示搜索结果。如果您在数据集中添加额外的字段,或需要审查如何显示该集的电影之外的数据,请注意这一点。

您现在可以使用您之前在package.json 中配置的npm start命令测试新的 Meilisearch 前端:

1npm start

npm start是运行 Node.js 应用程序的常见惯例,在这种情况下,npm start已配置为运行parcel:

1[secondary_label Output]
2> [email protected] start /root/instant
3> parcel index.html --global instantMeiliSearch
4
5Server running at http://localhost:1234
6✨  Built in 2.16s.

您现在应该有一个临时的包裹服务器,在https://your_domain/dev服务您的前端。在浏览器中导航到该URL,您应该能够访问您的Meilisearch界面。通过运行几个查询来尝试:

Stock meilisearch interface

在运行时,包裹服务器将阻止您的壳 – 您可以按Ctrl+C来阻止这个过程. 您现在有一个工作 Meilisearch 前端,可以部署到生产中。

步骤 4 – 定制您的 Meilisearch 界面

在此步骤中,您将添加面向界面到您的Meilisearch前端,并审查一些可选的widgets。

向 InstantSearch 界面添加额外的 widgets 有两个步骤:将<div>容器添加到您的 HTML 页面,并将这些容器绑定到search.addWidgets()块中声明的功能。

首先,打开 index.html 并将 <div class="left-panel"/> 块添加到文件中间,如下所示:

1nano index.html
 1[label index.html]
 2 3      <h2>Search Movies!</h2>
 4
 5      <div class="left-panel">
 6        <div id="clear-refinements"></div>
 7
 8        <h2>Genres</h2>
 9        <div id="genres-list"></div>
10      </div>
11
12      <div class="right-panel">
13

保存并关闭文件,然后打开app.js并添加相应的内容。

1nano app.js

请注意,容器:块与HTML中的<div/>块相匹配。

 1[label app.js]
 2import { instantMeiliSearch } from "@meilisearch/instant-meilisearch";
 3 4    container: "#searchbox"
 5  }),
 6  instantsearch.widgets.clearRefinements({
 7    container: "#clear-refinements"
 8  }),
 9  instantsearch.widgets.refinementList({
10    container: "#genres-list",
11    attribute: "genres"
12  }),
13  instantsearch.widgets.configure({
14    hitsPerPage: 6,
15

在做出这些更改后,重新启动您的包裹服务器以npm开始,以便在浏览器中看到它们:

1npm start

Meilisearch interface with added genre filter

许多其他 InstantSearch 小工具也与 Meilisearch 兼容,您可以在 项目文档中找到它们的实施细节。

在最后一步中,您将重新部署您的前端到永久 URL。

步骤 5 — 在生产中部署您的即时mellisearch应用程序

当你编辑上面的 package.json 时,你除了 start 命令之外,还提供了 build 命令. 你现在可以使用 npm run-script build (只有 start 得到缩短的 npm start 语法),来包装你的应用程序用于生产:

1npm run-script build
 1[secondary_label Output]
 2> [email protected] build /root/instant
 3> parcel build --global instantMeiliSearch index.html
 4
 5✨  Built in 7.87s.
 6
 7dist/app.426c3941.js.map 211.84 KB 43ms
 8dist/app.426c3941.js 48.24 KB 5.28s
 9dist/instant.0f565085.css.map 1.32 KB 4ms
10dist/index.html 872 B 2.41s
11dist/instant.0f565085.css 689 B 1.41s

这将生成一组文件,您可以从静态的网页目录中服务,而无需使用来运行临时服务器。 请记住, Nginx 仍然在默认 HTTP/HTTPS 端口上服务默认主页。 您可以将您刚刚生成的dist目录的内容复制到 Nginx 服务默认主页的目录中,即/var/www/html。 Nginx 将自动从您的 Meilise 前端服务到index.html文件:

1sudo cp dist/* /var/www/html/.

您现在应该能够在浏览器中导航到 https://your_domain 以访问您的 Meilisearch 前端. 因为 instant-meilisearch 被编译成一个静态的 Web 应用程序,只需要连接到正在运行的 meilisearch 实例,您可以部署前端到您想要的任何地方,包括在另一个服务器上,或在另一个静态托管提供商上。

结论

在本教程中,您为现有 Meilisearch 服务器创建并部署了 Meilisearch 前端,您使用了反向代理和 Node.js 工具,并审查了 Meilisearch 身份验证的其他细节,现在您可以进一步定制 Meilisearch 后端和前端,以创建其他接口来查询不同类型的数据。

接下来,您可能需要 试用网页扫描,以识别可以加载到 Meilisearch 的其他数据源。

Published At
Categories with 技术
Tagged with
comments powered by Disqus