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>
);
});