Algolia 搜索
Algolia 是一个搜索平台,提供了一套功能和 API,使您能够轻松地为用户实现强大的搜索体验。事实上,它开箱即用地提供了工具和基础设施,可以将快速且相关的搜索功能集成到我们的应用程序中。借助 Algolia API,将其集成到您的 Qwik 应用程序中非常简单。
解决方案
要开始使用它,您需要创建一个个人 Algolia 帐户并检索您的 API 密钥,这些密钥将用于与 Algolia 交互。
- 索引名称:索引是 Algolia 使用的数据存储位置。它相当于数据库中的表,但针对搜索和发现操作进行了优化。
- 应用程序 ID:这是您的唯一应用程序标识符。它用于在使用 Algolia API 时识别您。
- 仅搜索 API 密钥:这是您在前端代码中使用的公共 API 密钥。此密钥仅可用于搜索查询和将数据发送到 Insights API。
因此,一旦您拥有这些信息,您就可以通过在项目的根目录中创建或编辑 .env
或 .env.local
文件来定义您的环境变量。
.env
VITE_ALGOLIA_INDEX=
VITE_ALGOLIA_APP_ID=
VITE_ALGOLIA_SEARCH_KEY=
您可以在下面找到第一个可用实现的工作示例。然后,您可以自定义并创建自己的图形界面。很多时候,在显示搜索和结果的模态窗口中使用搜索是有意义的,例如您在此 Qwik 文档中找到的搜索。您可以通过 官方文档 检查 Algolia 返回的内容。
import { $, component$, useSignal, useStylesScoped$ } from '@builder.io/qwik';
type AlgoliaResult = {
hits: {
type: string;
anchor?: string;
content?: string;
url: string;
}[];
};
export default component$(() => {
useStylesScoped$(`
.search {
font-size: 100%;
width: calc(100% - 38px);
border-radius: 0.5rem;
border: 1px black solid;
padding: 1rem;
color: black;
outline: none;
}
.search-button {
border: none;
padding: 6px 0px;
cursor: pointer;
background-color: transparent;
position: absolute;
right: 2.4rem;
padding: 0.85rem 0.5rem 0.4rem 0.5rem;
outline: none;
}
.list {
display: flex;
flex-direction: column;
align-items: center;
}
.list li {
counter-increment: cardCount;
display: flex;
color: white;
margin-top: 1rem;
margin-bottom: 1rem;
max-width: 500px;
}
.list li::before {
content: counter(cardCount, decimal-leading-zero);
background: white;
color: var(--cardColor);
font-size: 2em;
font-weight: 700;
transform: translateY(calc(-1 * 1rem));
margin-right: calc(-1 * 1rem);
z-index: 1;
display: flex;
align-items: center;
padding-inline: 0.5em;
border: 1px solid black;
}
.list li .content {
background-color: var(--cardColor);
display: grid;
padding: 0.5em calc(1em + 1.5rem) 0.5em calc(1em + 1rem);
grid-template-areas:
"icon title"
"icon text";
gap: 0.25em;
clip-path: polygon(
0 0,
calc(100% - 1.5rem) 0,
100% 50%,
calc(100% - 1.5rem) 100%,
calc(100% - 1.5rem) calc(100% + 1rem),
0 calc(100% + 1rem)
);
}
.list li .content .title {
grid-area: title;
font-size: 1.25em;
}
.list li .content .text {
grid-area: text;
color: black;
}
`);
const termSignal = useSignal('');
const hitsSig = useSignal<AlgoliaResult['hits']>([]);
const onSearch = $(async (query: string) => {
const algoliaURL = new URL(
`/1/indexes/${import.meta.env.VITE_ALGOLIA_INDEX}/query`,
`https://${import.meta.env.VITE_ALGOLIA_APP_ID}-dsn.algolia.net`
);
const response = await fetch(algoliaURL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Algolia-Application-Id': import.meta.env.VITE_ALGOLIA_APP_ID!,
'X-Algolia-API-Key': import.meta.env.VITE_ALGOLIA_SEARCH_KEY!,
},
body: JSON.stringify({ query }),
});
const algoliaResult: AlgoliaResult = await response.json();
hitsSig.value = algoliaResult.hits;
});
return (
<div>
<div style="margin: 1rem;">
<div style="position: relative;">
<input
class="search"
placeholder="Algolia search: type here and press enter"
bind:value={termSignal}
onKeyDown$={(e) => {
if (e.key === 'Enter') {
onSearch(termSignal.value);
}
}}
/>
<button
type="submit"
class="search-button"
onClick$={() => onSearch(termSignal.value)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M15.5 14h-.79l-.28-.27A6.471 6.471 0 0 0 16 9.5A6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5S14 7.01 14 9.5S11.99 14 9.5 14z"
/>
</svg>
</button>
</div>
</div>
<div class="list">
{hitsSig.value.map(({ anchor, content, url }, key) => (
<li
key={key}
style={`--cardColor:${key % 2 === 0 ? '#19b6f6' : '#ac7ef4'}`}
>
<div class="content">
<div class="title">
{(anchor || content || url || '').substring(0, 30)}
</div>
<a class="text" href={url}>
Documentation link
</a>
</div>
</li>
))}
</div>
</div>
);
});