Meilisearch 允许您通过 RESTful API 在极短时间内搜索您的数据。在开发模式下,它提供一个搜索预览,您可以在其中测试您的搜索设置,而无需实现前端。

Meilisearch's search preview

我知道它很漂亮,但不幸的是,它只对开发人员可见。如果您需要为最终用户提供前端搜索界面,您需要自己动手。但别担心,这并不像听起来那么难。在本教程中,您将学习如何轻松创建自定义前端搜索。为此,我们将使用两个主要工具

它们结合在一起,使您能够轻松地将令人愉快的搜索体验集成到您的前端。

介绍数据集

本教程中使用的数据集直接参考了我们 Strapi 教程 中使用的数据集。我们使用 faker(一个生成假数据的库)添加了更多虚拟餐厅。我们为餐厅添加了一个 picture 字段,其中包含来自 Unsplash 的随机餐厅图片 URL。每家餐厅都有以下字段

  • name
  • description
  • picture
  • categories

我们添加了两个额外的字段来帮助我们为图片作者提供署名

  • picture_author
  • picture_author_profile_link

前端将如下所示

Searching for “bakery” in the restaurant demo using Meilisearch

需求

  1. 运行中的 Meilisearch v1 实例,已索引 餐厅数据集。如果您需要有关此部分的帮助,您可以按照我们的 快速入门指南 进行操作,直到 添加文档 这一步。运行 Meilisearch 实例的最简单方法是使用 Meilisearch Cloud,提供 14 天免费试用,无需信用卡。
  2. 具有以下已安装软件包的 React 环境
yarn add @meilisearch/instant-meilisearch@^0.11.1 instantsearch.css@^8.0.0 react-instantsearch-dom@^6.39.1
👉
我们已预先选择了上面的特定软件包版本,以确保本教程具有较长的使用寿命。请注意,如果未遵守这些版本,本教程可能无法按预期运行。如果您使用的是这些软件包的较新版本,您可能需要检查它们的变更日志,以了解自发布本文以来它们是如何演变的。

要轻松创建单页 React 应用程序,您可以使用 Create React App

代码

对于本示例,我们只需要两个文件:App.jsindex.jsApp.js 将包含您的应用程序代码,而 index.js 将初始化您的 React 应用程序。

您的 index.js 文件应如下所示

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

您无需修改 index.js,因此让我们看一下 App.js 的代码。

import "instantsearch.css/themes/algolia-min.css";
import React from "react";
import {
  InstantSearch,
  InfiniteHits,
  SearchBox,
  Stats,
  Highlight
} from "react-instantsearch-dom";
import "./App.css";
import { instantMeiliSearch } from "@meilisearch/instant-meilisearch";

const searchClient = instantMeiliSearch(
  "http://localhost:7700",
  ""
);

const App = () => (
  <div className="ais-InstantSearch">
    <h1>Restaurants Demo with Meilisearch</h1>
    <InstantSearch indexName="restaurant" searchClient={searchClient}>
      <Stats />
      <SearchBox />
      <InfiniteHits hitComponent={Hit} />
    </InstantSearch>
  </div>
);

const Hit = ({ hit }) => (
  <div key={hit.id}>
    <div className="hit-name">
      <Highlight attribute="name" hit={hit} />
    </div>
    <p className="hit-categories"><Highlight attribute="categories" hit={hit} /></p>
    <div className="hit-image">
      <img src={hit.picture} alt={hit.name} width="200px" />
      <p className="image-credit">Picture by <a href={hit.picture_author_profile_link}>{hit.picture_author}</a> on <a href="https://unsplash.com/?utm_source=restaurants_demo&utm_medium=referral">Unsplash</a></p>
    </div>
    <div className="hit-description">
      <Highlight attribute="description" hit={hit} />
    </div>
  </div>
);

export default App;

让我们逐个组件进行分析。

导入所需的组件

以下代码行导入我们需要的搜索组件和客户端,以及样式。

import "instantsearch.css/themes/algolia-min.css";
import React from "react";
import {
  InstantSearch,
  InfiniteHits,
  SearchBox,
  Stats,
  Highlight
} from "react-instantsearch-dom";
import "./App.css";
import { instantMeiliSearch } from "@meilisearch/instant-meilisearch";

初始化搜索客户端

接下来,我们需要初始化将与 Meilisearch 通信的搜索客户端。将您的 Meilisearch 凭据(主机和 API 密钥)添加为 instantMeilisearch 函数的第一个和第二个参数。如果您已按照我们的 快速入门指南 逐字进行,您的 Meilisearch 主机应该是 http://127.0.0.1:7700。由于我们未设置任何 API 密钥,因此我们可以将第二个参数保留为空字符串。

const searchClient = instantMeiliSearch(
  "http://localhost:7700",
  "" //your Meilisearch API key, if any
);
👉
默认情况下,Meilisearch 的 API 是不受保护的。要保护 Meilisearch 实例免受未经授权的使用,您必须在启动时提供主密钥。您可以在我们的 文档 中了解更多信息。

添加我们的组件

以下代码添加了我们需要的不同组件

const App = () => (
  <div className="ais-InstantSearch">
    <h1>Restaurants Demo with Meilisearch</h1>
    <InstantSearch indexName="restaurant" searchClient={searchClient}>
      <Stats />
      <SearchBox />
      <InfiniteHits hitComponent={Hit} />
    </InstantSearch>
  </div>
);

const Hit = ({ hit }) => (
  <div key={hit.id}>
    <div className="hit-name">
      <Highlight attribute="name" hit={hit} />
    </div>
    <p className="hit-categories"><Highlight attribute="categories" hit={hit} /></p>
    <div className="hit-image">
      <img src={hit.picture} alt={hit.name} width="200px" />
      <p className="image-credit">Picture by <a href={hit.picture_author_profile_link}>{hit.picture_author}</a> on <a href="https://unsplash.com/?utm_source=restaurants_demo&utm_medium=referral">Unsplash</a></p>
    </div>
    <div className="hit-description">
      <Highlight attribute="description" hit={hit} />
    </div>
  </div>
);

export default App;

让我们一步一步地了解每个组件的作用

  • <InstantSearch>:我们的即时搜索的强制包装器。我们需要将 searchClient 作为道具提供给此组件,以及 索引名称
  • <Stats>:显示文档数量和 Meilisearch 查找搜索结果所花费的时间
  • <SearchBox>:添加搜索栏
  • <InfiniteHits>:不同 Hits 的包装器。它将 Hit(在第 29 行声明)作为道具。
  • Hit:我们创建的自定义组件,用于确定要展示餐厅的哪些属性

Hit 组件

const Hit = ({ hit }) => (
  <div key={hit.id}>
    <div className="hit-name">
      <Highlight attribute="name" hit={hit} />
    </div>
    <p className="hit-categories"><Highlight attribute="categories" hit={hit} /></p>
    <div className="hit-image">
      <img src={hit.picture} alt={hit.name} width="200px" />
      <p className="image-credit">Picture by <a href={hit.picture_author_profile_link}>{hit.picture_author}</a> on <a href="https://unsplash.com/?utm_source=restaurants_demo&utm_medium=referral">Unsplash</a></p>
    </div>
    <div className="hit-description">
      <Highlight attribute="description" hit={hit} />
    </div>
  </div>
);
  • <img>hit.picture 作为道具来显示每家餐厅的图片
  • <Highlight> 组件将属性作为道具,如果该属性中包含查询匹配项,则会突出显示匹配项。第一个是 name,第二个是 categories,第三个是 description。

就是这样;只需几行代码,我们就构建了一个搜索界面。我留给您去个性化它,并用一些 CSS 💅 美化它。

结论

为了更进一步,我们可以使用过滤器来创建一个 多面搜索 界面,并允许用户根据餐厅类别细化搜索结果。但我希望本教程尽可能简单,以帮助您了解将 InstantSearch.js 与 Meilisearch 集成以创建出色的搜索体验是多么容易!

👉 不使用 React?别担心;我们还有其他前端集成。查看 GitHub 上的 列表

想要了解更多关于 Meilisearch 提供的自定义选项?您可以查看 Meilisearch 101

如果您有任何问题,请加入我们的 Discord;我们很乐意听到您的声音。如果您想支持我们,您可以为我们的 GitHub 仓库 加星或分享我们的作品 🥰