介绍
在本教程中,您将学习如何轻松创建基于搜索的 Web 应用程序,并利用 Meilisearch 的强大功能获得即时可靠的结果。
我们将介绍将数据添加到 Meilisearch 的基本步骤,创建自定义前端搜索,并在最后进行自定义。
在本教程中,我们将为一个运动品牌创建即时搜索体验。以下是您将构建的内容的预览

先决条件
在开始之前,请确保您已在计算机上安装了 Node.js >= 18。
您可以按照本教程进行操作,并在执行步骤时编写代码,使用此GitHub 项目。
最后,本教程假定您已经熟悉 React。如果不是,您可以查看 React 文档以了解更多信息。
入门
克隆存储库
使用以下命令克隆 GitHub 存储库
git clone https://github.com/meilisearch/tutorials.git
cd src/react-decathlon
运行新的 Docker 镜像
如果您克隆了存储库以设置 Meilisearch 实例,只需在主文件夹中执行以下命令
npm install
npm run setup_meili
如果您没有克隆存储库,并且想要使用 Docker 启动 Meilisearch,请执行以下命令
docker run -it --rm \
-p 7700:7700 \
-e MEILI_ENV='development' \
-v $(pwd)/meili_data:/meili_data \
getmeili/meilisearch:v1.0
您可以通过访问以下地址来检查 Meilisearch 是否正在运行: http://localhost:7700/
想要避免本地安装?为了快速创建一流的搜索体验,我们提供Meilisearch Cloud 的便利,它是一个托管的、完全管理的 Meilisearch 版本。提供 14 天免费试用,无需信用卡 😉
在 Meilisearch 中创建索引
索引是存储文档的实体,就像带有特定设置的数组对象,以及唯一的主键。
每个索引的文档都必须有一个主字段,它是一个特殊字段,必须存在于所有文档中。该字段保存文档的唯一值:它的 ID。
Meilisearch 可以从您的数据集中推断主键,前提是它包含 id
子字符串。您也可以显式设置它。
以下是一个要添加到 Meilisearch 的示例文档。
{
"id": 100013768717,
"name": "Fitness Foldable Shoe Bag",
"url": "https://www.decathlon.com/products/gym-foldable-shoe-bag",
"vendor": "Domyos",
"category": "Sport bag",
"tags": [
"Artistic Gymnastics",
"Boy's",
"CARDIO_FITNESS_ACCESSORIES",
"CARDIO_FITNESS_BAGS",
"CODE_R3: 11782"
],
"images": "https://cdn.shopify.com/s/files/1/1330/6287/products/sac_20a_20chaussure_20kaki_20_7C_20001_20_7C_20PSHOT_20_490180e6-44e4-4340-8e3d-c29eb70c6ac8.jpg?v=1584683232",
"creation_date": "2020-04-03T15:58:48-07:00",
"price": "2.49"
}
您可以使用像 Postman 这样的 REST 客户端轻松创建此索引,但在本教程中,我们将使用 Meilisearch Javascript SDK 直接从 Node.js 执行操作。
const { MeiliSearch } = require('meilisearch')
;(async () => {
try {
const config = {
host: 'http://localhost:7700'
};
const meili = new MeiliSearch(config);
await meili.createIndex('decathlon');
// or you can set the primary key explicitly:
// await meili.createIndex({ uid: "decathlon", primaryKey: "id" });
} catch (e) {
console.error(e);
console.log("Meili error: ", e.message);
}
})();
您可以在Meilisearch 文档 中了解有关索引属性的更多信息。
索引文档
Meilisearch 以 JSON 格式接收文档,并将其存储以供搜索。这些文档由可以保存任何类型数据的字段组成。Meilisearch 还接受以下格式的数据集:NDJSON 和 CSV。您可以在文档 中了解有关格式的更多信息。
在本教程中,您可以下载这个包含运动服装的完整数据集: decathlon.json
使用以下脚本将此 JSON 文件中的所有对象上传到 Meilisearch。在运行它之前,请记住更改 JSON 文件的路径!
const { MeiliSearch } = require('meilisearch')
;(async () => {
try {
const config = {
host: 'http://localhost:7700'
};
const meili = new MeiliSearch(config);
const decathlon = require("../decathlon.json"); // path to json file
const index = meili.index("decathlon");
await index.addDocuments(decathlon);
} catch (e) {
console.error(e);
console.log("Meili error: ", e.message);
}
})();
准备 React 应用程序
我们需要一个标准的 React 应用程序。您可以使用您之前在入门 部分克隆的项目。
如果您更愿意从一个空应用程序开始,您可以使用以下命令使用Create React App 创建自己的应用程序。您可以随意命名应用程序。
npx create-react-app meili_react_demo
cd meili_react_demo
包含 Tailwind CSS
为了加快样式设置过程,请将Tailwind CSS 样式直接添加到 index.html 文件的 <head>
元素中
<script src="https://cdn.tailwindcss.com"></script>
配置 App.js 状态
然后,使用以下代码修改 App.js
文件,以设置一个简单的搜索表单,以及一些状态变量来处理搜索的各个方面。
import React, { useState, useEffect } from 'react'
import { MeiliSearch } from 'meilisearch'
import Item from './components/Item'
// TODO configure the MeiliSearch Client
const index = client.index('decathlon')
function App () {
const [searchedWord, setSearch] = useState('')
const [resultSearch, setResults] = useState([])
// TODO add function to send searchedWord to Meilisearch
return (
<div className='mx-auto'>
<div className='header font-sans text-white items-center justify-center'>
<header className='py-12'>
<img
className='h-20 w-auto items-center justify-center p-2 mx-auto'
src='/wide_logo.png'
style={{ filter: 'invert(0%)' }}
alt='Decathlon logo'
/>
<h1 className='flex flex-wrap flex-grow text-3xl w-full justify-center p-4'>
Stop looking for an item — find it and work hard!
</h1>
<div className='border rounded overflow-hidden w-full flex justify-center mx-auto searchBox mt-6'>
<button className='flex items-center justify-center px-4 shadow-md bg-white text-black'>
<svg
className='h-4 w-4 text-grey-dark'
fill='currentColor'
xmlns='http://www.w3.org/2000/svg'
viewBox='0 0 24 24'
>
<path d='M16.32 14.9l5.39 5.4a1 1 0 0 1-1.42 1.4l-5.38-5.38a8 8 0 1 1 1.41-1.41zM10 16a6 6 0 1 0 0-12 6 6 0 0 0 0 12z' />
</svg>
</button>
<input
type='text'
value={searchedWord}
onChange={(event) => setSearch(event.target.value)}
className='px-6 py-4 w-full text-black'
placeholder='Product, sport, color, …'
/>
</div>
</header>
</div>
<div>
<div className='flex flex-wrap searchResults'>
// TODO iterate over the search results to display them with the Item component
</div>
</div>
</div>
)
}
export default App
此代码应该输出一个带搜索表单的漂亮标题。

React 中的搜索结果
使用 Javascript SDK 将 React 连接到 Meilisearch 是一项简单的操作,只需几个步骤即可完成。
Meilisearch 客户端
使用以下命令安装 Meilisearch SDK
// if you use npm
npm install meilisearch
// if you use yarn
yarn add meilisearch
使用服务器 URL 设置 Meilisearch 客户端。在本例中,它是 localhost Docker 机器。最后,从后端加载正确的索引。
将 App.js
中的以下注释替换为下面的代码片段
"// TODO 配置 Meilisearch 客户端"
import { MeiliSearch } from "meilisearch";
const client = new MeiliSearch({
host: "http://localhost:7700/",
});
const index = client.index("decathlon");
发送搜索查询
添加一个 useEffect
钩子来执行对 Meilisearch 中输入的文字进行搜索。所有结果将被设置为一个名为 resultsSearch
的简单状态变量。
将 App.js
中的以下注释替换为下面的代码片段
"// TODO 添加函数以将 searchedWord 发送到 Meilisearch"
useEffect(() => {
// Create a scoped async function in the hook
async function searchWithMeili() {
const search = await index.search(searchedWord);
setResults(search.hits);
}
// Execute the created function directly
searchWithMeili();
}, [searchedWord]);
展示结果
您将迭代 Meilisearch 返回的 JSON 对象(它们的结构与上传的 JSON 对象相同),并将它们显示在 Item
组件中,链接到产品页面。
让我们创建 Item
组件,它将帮助我们显示我们的产品。在 components 文件夹中创建一个 Item.js
文件,并将以下代码片段粘贴进去
function Item ({ url, image, name, category, vendor, price, id }) {
return (
<div className='flex w-full sm:w-1/2 md:w-1/3 lg:w-1/4 xl:w-1/6 p-3' key={id}>
<a className='flex-1 rounded overflow-hidden shadow-lg' href={url}>
<img
className='w-full h-48 object-cover'
src={image}
alt={name}
onError={(e) => {
e.target.onerror = null
e.target.src = '/wide_logo.png'
}}
/>
<div className='px-6 py-3'>
<div className='font-bold text-sm mb-1 text-gray-600 capitalize'>
{category}
</div>
{name}
<div className='font-bold text-xl mb-2 text-gray-800'>
{vendor} -
</div>
<p className='text-black text-xl font-bold text-base py-2'>
$ {price}
</p>
</div>
</a>
</div>
)
}
export default Item
然后,将 App.js
中的以下注释替换为下面的代码片段
{resultSearch?.map((result) => (
<Item
url={result.url}
image={result.images}
name={result.name}
category={result.category}
vendor={result.vendor}
price={result.price}
key={result.id}
/>
))}
您可以在GitHub 上查看完整代码。

配置搜索
使用 Meilisearch,您可以获得大量自定义选项,以微调您的搜索体验。我们将在此处介绍一些功能。您可以在文档 中了解有关它们的更多信息。
搜索排名
我们将从更改排名规则开始,即 Meilisearch 在执行搜索查询时用于对您上传的文档进行排序的标准。排名规则的顺序会影响搜索结果的相关性。您可以在文档 中了解有关它的更多信息。
让我们使用以下顺序
[
"words",
"typo",
"proximity",
"attribute",
"sort",
"exactness",
“creation_date:desc”
]
这使用了默认顺序以及自定义规则:creation_date
。此规则根据创建日期对项目进行排名,前提是所有先前的值都相同。
可搜索属性
您还可以配置可搜索属性。这些是 Meilisearch 在其中搜索与查询词匹配的值的属性。默认情况下,所有属性都是可搜索的,但您可以对其进行配置,使其仅搜索 name
、vendor
、category
和 tags
字段,而忽略 images
和 URL
searchableAttributes: ["name", "vendor", "category", "tags"]
显示的属性
显示的属性是 Meilisearch 可以使用displayedAttributes 数组返回给用户的前端应用程序中的属性。与可搜索属性一样,默认情况下所有属性都将显示。
"displayedAttributes": [
"name",
"vendor",
"category",
"tags",
"images",
"url"
]
将新设置上传到 Meilisearch
现在是时候使用上面解释的搜索设置自定义我们的 Meilisearch 索引了。
const { MeiliSearch } = require('meilisearch')
;(async () => {
try {
const config = {
host: 'http://localhost:7700'
};
const meili = new MeiliSearch(config);
const index = meili.index("decathlon");
const newSettings = {
rankingRules: [
"words",
"typo",
"proximity",
"attribute",
"sort",
"exactness",
"creation_date:desc"
],
searchableAttributes: ["name", "vendor", "category", "tags"],
displayedAttributes: [
"name",
"vendor",
"category",
"tags",
"images",
"url"
]
};
await index.updateSettings(newSettings);
} catch (e) {
console.error(e);
console.log("Meili error: ", e.message);
}
})();
结论
如果没有一个不可思议的团队日夜为这个伟大的项目工作,这个快速搜索是不可能实现的!如果您喜欢为 Meilisearch 家族做出贡献,请查看以下存储库
通过订阅我们的时事通讯,让这些每月更新直接发送到您的收件箱。
有关 Meilisearch 的更多信息,请加入我们开发者社区的Discord。您可以通过查看路线图 并参与产品讨论 来了解更多关于该产品的信息。