Algolia 搜索

algolia-search
分类通用
作者Agentic Awesome Skills 社区
许可MIT
评分4.60/5
使用8.6K

Algolia 搜索集成

Algolia 搜索实现、索引策略、React InstantSearch 及相关性调优的专家级模式

模式 (Patterns)

基于 Hooks 的 React InstantSearch

使用 hooks 实现类型前置搜索(type-ahead search)的现代 React InstantSearch 配置。

使用 react-instantsearch-hooks-web 包和 algoliasearch 客户端。
Widget 是可以通过 classnames 自定义的组件。

核心 hooks:

  • useSearchBox:处理搜索输入

  • useHits:访问搜索结果

  • useRefinementList:分面过滤 (Facet filtering)

  • usePagination:结果分页

  • useInstantSearch:访问完整状态

代码示例 (Code_example)

tsx
// lib/algolia.ts
import algoliasearch from 'algoliasearch/lite';

export const searchClient = algoliasearch(
process.env.NEXT_PUBLIC_ALGOLIA_APP_ID!,
process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY! // 仅限搜索的 Key!
);

export const INDEX_NAME = 'products';

// components/Search.tsx
'use client';
import { InstantSearch, SearchBox, Hits, Configure } from 'react-instantsearch';
import { searchClient, INDEX_NAME } from '@/lib/algolia';

function Hit({ hit }: { hit: ProductHit }) {
return (
<article>
<h3>{hit.name}</h3>
<p>{hit.description}</p>
<span>${hit.price}</span>
</article>
);
}

export function ProductSearch() {
return (
<InstantSearch searchClient={searchClient} indexName={INDEX_NAME}>
<Configure hitsPerPage={20} />
<SearchBox
placeholder="Search products..."
classNames={{
root: 'relative',
input: 'w-full px-4 py-2 border rounded',
}}
/>
<Hits hitComponent={Hit} />
</InstantSearch>
);
}

// 自定义 hook 用法
import { useSearchBox, useHits, useInstantSearch } from 'react-instantsearch';

function CustomSearch() {
const { query, refine } = useSearchBox();
const { hits } = useHits<ProductHit>();
const { status } = useInstantSearch();

return (
<div>
<input
value={query}
onChange={(e) => refine(e.target.value)}
placeholder="Search..."
/>
{status === 'loading' && <p>Loading...</p>}
<ul>
{hits.map((hit) => (
<li key={hit.objectID}>{hit.name}</li>
))}
</ul>
</div>
);
}

反模式 (Anti_patterns)

  • 模式:在前端代码中使用 Admin API key | 原因:Admin key 暴露了包括删除在内的完整索引控制权 | 修复:使用带有权限限制的 search-only API key
  • 模式:前端不使用 /lite 客户端 | 原因:完整客户端包含搜索不需要的冗余代码 | 修复:从 algoliasearch/lite 导入以减小 bundle 体积

参考资料 (References)

  • https://www.algolia.com/doc/api-reference/widgets/react
  • https://www.algolia.com/doc/libraries/javascript/v5/methods/search/

Next.js 服务端渲染 (SSR)

使用 react-instantsearch-nextjs 包在 Next.js 中集成 SSR。

使用 <InstantSearchNext> 代替 <InstantSearch> 以实现 SSR。
同时支持 Pages Router 和 App Router(实验性)。

关键注意事项:

  • 设置 dynamic = 'force-dynamic' 以确保结果实时

  • 通过 routing 属性处理 URL 同步

  • 使用 getServerState 获取初始状态

代码示例 (Code_example)

tsx
// app/search/page.tsx
import { InstantSearchNext } from 'react-instantsearch-nextjs';
import { searchClient, INDEX_NAME } from '@/lib/algolia';
import { SearchBox }
, Hits, RefinementList } from 'react-instantsearch';

// 强制动态渲染以确保搜索结果最新
export const dynamic = 'force-dynamic';

export default function SearchPage() {
return (
<InstantSearchNext
searchClient={searchClient}
indexName={INDEX_NAME}
routing={{
router: {
cleanUrlOnDispose: false,
},
}}
>
<div className="flex gap-8">
<aside className="w-64">
<h3>Categories</h3>
<RefinementList attribute="category" />
<h3>Brand</h3>
<RefinementList attribute="brand" />
</aside>
<main className="flex-1">
<SearchBox placeholder="Search products..." />
<Hits hitComponent={ProductHit} />
</main>
</div>
</InstantSearchNext>
);
}

// 用于自定义路由(URL 同步)
import { history } from 'instantsearch.js/es/lib/routers';
import { simple } from 'instantsearch.js/es/lib/stateMappings';

<InstantSearchNext
searchClient={searchClient}
indexName={INDEX_NAME}
routing={{
router: history({
getLocation: () =>
typeof window === 'undefined'
? new URL(url) as unknown as Location
: window.location,
}),
stateMapping: simple(),
}}
>
{/* widgets */}
</InstantSearchNext>

反模式 (Anti-patterns)

  • 模式:在 Next.js SSR 中使用 InstantSearch 组件 | 原因:普通组件不支持服务端渲染 | 修复:使用 react-instantsearch-nextjs 中的 InstantSearchNext
  • 模式:对搜索页面使用静态渲染 | 原因:搜索结果在每次请求时必须是最新的 | 修复:设置 export const dynamic = 'force-dynamic'

参考资料

  • https://www.npmjs.com/package/react-instantsearch-nextjs
  • https://www.algolia.com/developers/code-exchange/instantsearch-and-next-js-starter

数据同步与索引

确保 Algolia 与数据保持同步的索引策略。

三种主要方法:
1. 全量重新索引 (Full Reindexing) - 替换整个索引(成本较高)
2. 全量记录更新 (Full Record Updates) - 替换单个记录
3. 部分更新 (Partial Updates) - 仅更新特定属性

最佳实践:

  • 批量处理记录(理想情况:每批 10MB,1K-10K 条记录)

  • 尽可能使用增量更新

  • 仅针对属性更改使用 partialUpdateObjects

  • 避免使用 deleteBy(计算开销较大)

代码示例

// lib/algolia-admin.ts (仅限服务端)
import algoliasearch from 'algoliasearch';

// 管理员客户端 - 切勿暴露给前端
const adminClient = algoliasearch(
process.env.ALGOLIA_APP_ID!,
process.env.ALGOLIA_ADMIN_KEY! // 用于索引的管理员密钥
);

const index = adminClient.initIndex('products');

// 批量索引(推荐方法)
export async function indexProducts(products: Product[]) {
const records = products.map((p) => ({
objectID: p.id, // 必需的唯一标识符
name: p.name,
description: p.description,
price: p.price,
category: p.category,
inStock: p.inventory > 0,
createdAt: p.createdAt.getTime(), // 使用时间戳进行排序
}));

// 每批约 1000-5000 条记录进行分块处理
const BATCH_SIZE = 1000;
for (let i = 0; i < records.length; i += BATCH_SIZE) {
const batch = records.slice(i, i + BATCH_SIZE);
await index.saveObjects(batch);
}
}

// 部分更新 - 仅更新特定字段
export async function updateProductPrice(productId: string, price: number) {
await index.partialUpdateObject({
objectID: productId,
price,
updatedAt: Date.now(),
});
}
使用操作进行部分更新

typescript
export async function incrementViewCount(productId: string) {
await index.partialUpdateObject({
objectID: productId,
viewCount: {
_operation: 'Increment',
value: 1,
},
});
}

// 删除记录(优先使用此方法而非 deleteBy)

typescript
export async function deleteProducts(productIds: string[]) {
await index.deleteObjects(productIds);
}

// 零停机全量重新索引(原子交换)

typescript
export async function fullReindex(products: Product[]) {
const tempIndex = adminClient.initIndex('products_temp');

// 索引到临时索引
await tempIndex.saveObjects(
products.map((p) => ({
objectID: p.id,
...p,
}))
);

// 从主索引复制设置
await adminClient.copyIndex('products', 'products_temp', {
scope: ['settings', 'synonyms', 'rules'],
});

// 原子交换
await adminClient.moveIndex('products_temp', 'products');
}

反模式 (Anti-patterns)

  • 模式:使用 deleteBy 进行批量删除 | 原因deleteBy 计算开销大且有频率限制 | 修复:使用 deleteObjects 并传入 objectIDs 数组
  • 模式:一次索引一条记录 | 原因:会产生索引队列,降低处理速度 | 修复:以 1K-10K 为一组进行批量记录处理
  • 模式:针对微小更改进行全量重新索引 | 原因:浪费操作次数,且比增量更新慢 | 修复:针对属性更改使用 partialUpdateObject

参考资料

  • https://www.algolia.com/doc/guides/sending-and-managing-data/send-and-update-your-data/in-depth/the-different-synchronization-strategies
  • https://www.algolia.com/blog/engineering/search-indexing-best-practices-for-top-performance-with-code-samples

API 密钥安全与限制

Algolia 的安全 API 密钥配置。

密钥类型:

  • Admin API Key:全权控制(索引、设置、删除)

  • Search-Only API Key:适用于前端,安全性高

  • Secured API Keys:基于基础密钥生成的带限制密钥

可用限制:

  • Indices:限制可访问的索引

  • Rate limit:限制每个 IP 每小时的 API 调用次数

  • Validity:设置过期时间

  • HTTP referrers:限制特定的 URL 来源

  • Query parameters:强制执行搜索参数

代码示例

typescript
// 绝对不要这样做 - 在前端使用 admin key
// const client = algoliasearch(appId, ADMIN_KEY);  // 错误!

// 正确做法:在前端使用 search-only key
const searchClient = algoliasearch(
process.env.NEXT_PUBLIC_ALGOLIA_APP_ID!,
process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY!
);

// 服务端:生成安全 API 密钥
// lib/algolia-secured-key.ts
import algoliasearch from 'algoliasearch';

const adminClient = algoliasearch(
process.env.ALGOLIA_APP_ID!,
process.env.ALGOLIA_ADMIN_KEY!
);

// 生成用户特定的安全密钥
export function generateSecuredKey(userId: string) {
const searchKey = process.env.ALGOLIA_SEARCH_KEY!;

return adminClient.generateSecuredApiKey(searchKey, {
// 用户只能看到自己的数据
filters: userId:${userId},
// 密钥 1 小时后过期
validUntil: Math.floor(Date.now() / 1000) + 3600,
// 限制在特定索引
restrictIndices: ['user_documents'],
});
}

// 为公共 API 创建限流密钥
export async function createRateLimitedKey() {
const { key } = await adminClient.addApiKey({
acl: ['search'],
indexes: ['products'],
description: 'Public search with rate limit',
maxQueriesPerIPPerHour: 1000,
referers: ['https://mysite.com/*'],
validity: 0, // 永不过期
});

return key;
}

// 获取用户安全密钥的 API 接口
// app/api/search-key/route


e.ts
import { auth } from '@/lib/auth';
import { generateSecuredKey } from '@/lib/algolia-secured-key';

export async function GET() {
const session = await auth();
if (!session?.user) {
return Response.json({ error: 'Unauthorized' }, { status: 401 });
}

const securedKey = generateSecuredKey(session.user.id);

return Response.json({ key: securedKey });
}

反模式 (Anti-patterns)

  • 模式:在客户端代码中硬编码 Admin API 密钥 | 原因:将索引的完整控制权暴露给攻击者 | 修复:使用带有权限限制的仅搜索密钥
  • 模式:所有用户使用同一个密钥 | 原因:无法针对每个用户限制数据访问 | 修复:使用用户过滤器生成安全 API 密钥
  • 模式:公共搜索缺乏频率限制 | 原因:机器人可能会耗尽你的搜索配额 | 修复:在 API 密钥上设置 maxQueriesPerIPPerHour

参考资料

  • https://www.algolia.com/doc/guides/security/api-keys
  • https://support.algolia.com/hc/en-us/articles/14339249272977-What-are-the-best-practices-to-manage-Algolia-API-keys-in-my-code-and-protect-them

自定义排序与相关性调优

配置可搜索属性和自定义排序以优化相关性。

可搜索属性(顺序很重要):
1. 最重要的字段优先(如 title, name)
2. 次要字段随后(如 description, tags)
3. 排除不可搜索的字段(如 image_url, id)

自定义排序:

  • 添加业务指标(如 popularity, rating, date)

  • 使用 desc() 表示降序,asc() 表示升序

代码示例

// scripts/configure-index.ts
import algoliasearch from 'algoliasearch';

const adminClient = algoliasearch(
process.env.ALGOLIA_APP_ID!,
process.env.ALGOLIA_ADMIN_KEY!
);

const index = adminClient.initIndex('products');

async function configureIndex() {
await index.setSettings({
// 可搜索属性,按重要程度排序
searchableAttributes: [
'name', // 最重要
'brand',
'category',
'description', // 最不重要
],

// 用于分面/过滤的属性
attributesForFaceting: [
'category',
'brand',
'filterOnly(inStock)', // 仅用于过滤,不显示
'searchable(tags)', // 可搜索的分面
],

// 自定义排序(在文本相关性之后生效)
customRanking: [
'desc(popularity)', // 最热门优先
'desc(rating)', // 然后按评分
'desc(createdAt)', // 然后按最新日期
],

// 容错设置
typoTolerance: true,
minWordSizefor1Typo: 4,
minWordSizefor2Typos: 8,

// 查询设置
queryLanguages: ['en'],
removeStopWords: ['en'],

// 高亮显示
attributesToHighlight: ['name', 'description'],
highlightPreTag: '<mark>',
highlightPostTag: '</mark>',

// 分页
hitsPerPage: 20,
paginationLimitedTo: 1000,

// 去重 (Distinct)
attributeForDistinct: 'productFamily',
distinct: true,
});

// 添加同义词
await index.saveSynonyms([
{
objectID: 'phone-mobile',
type: 'synonym',
synonyms: ['phone', 'mobile', 'cell', 'smartphone'],
},
{
objectID: 'laptop-notebook',
type: 'oneWaySynonym',
input: 'laptop',
synonyms: ['notebook', 'portable computer'],
},
]);

// 添加规则(基于查询的自定义)
await index.saveRules([
{
objectID: 'boost-sale-items',
condition: {
anchoring: 'contains',
pattern: 'sale',
},
consequence: {
params: {
filters: 'onSale:true',
optionalF
ilters: ['featured:true'],
},
},
},
]);

console.log('Index configured successfully');
}

configureIndex();

反模式 (Anti-patterns)

  • 模式:对所有属性进行同等权重搜索 | 原因:降低相关性,导致描述中的匹配项与标题匹配项权重相同 | 修复:按重要程度排列 searchableAttributes
  • 模式:缺乏自定义排序 | 原因:仅依赖文本匹配,忽略了业务价值 | 修复:在 customRanking 中加入流行度、评分或新鲜度
  • 模式:将原始日期作为字符串索引 | 原因:无法正确按日期排序 | 修复:使用时间戳 (getTime()) 进行日期排序

参考资料

  • https://www.algolia.com/doc/guides/managing-results/relevance-overview
  • https://www.algolia.com/doc/guides/managing-results/must-do/custom-ranking

分面搜索与过滤 (Faceted Search and Filtering)

使用精炼列表 (refinement lists)、范围滑块 (range sliders) 和层级菜单 (hierarchical menus) 实现分面导航。

组件类型:

  • RefinementList:多选复选框

  • Menu:单选列表

  • HierarchicalMenu:嵌套类别

  • RangeInput/RangeSlider:数值范围

  • ToggleRefinement:布尔值过滤器

代码示例

'use client';
import {
InstantSearch,
SearchBox,
Hits,
RefinementList,
HierarchicalMenu,
RangeInput,
ToggleRefinement,
ClearRefinements,
CurrentRefinements,
Stats,
SortBy,
} from 'react-instantsearch';
import { searchClient, INDEX_NAME } from '@/lib/algolia';

export function ProductSearch() {
return (
<InstantSearch searchClient={searchClient} indexName={INDEX_NAME}>
<div className="flex gap-8">
{/* 过滤器侧边栏 */}
<aside className="w-64 space-y-6">
<ClearRefinements />
<CurrentRefinements />

{/* 类别层级 */}
<div>
<h3 className="font-semibold mb-2">Categories</h3>
<HierarchicalMenu
attributes={[
'categories.lvl0',
'categories.lvl1',
'categories.lvl2',
]}
limit={10}
showMore
/>
</div>

{/* 品牌过滤器 */}
<div>
<h3 className="font-semibold mb-2">Brand</h3>
<RefinementList
attribute="brand"
searchable
searchablePlaceholder="Search brands..."
showMore
limit={5}
showMoreLimit={20}
/>
</div>

{/* 价格范围 */}
<div>
<h3 className="font-semibold mb-2">Price</h3>
<RangeInput
attribute="price"
precision={0}
classNames={{
input: 'w-20 px-2 py-1 border rounded',
}}
/>
</div>

{/* 库存开关 */}
<ToggleRefinement
attribute="inStock"
label="In Stock Only"
on={true}
/>

{/* 评分过滤器 */}
<div>
<h3 className="font-semibold mb-2">Rating</h3>
<RefinementList
attribute="rating"
transformItems={(items) =>
items.map((item) => ({
...item,
label: '★'.repeat(Number(item.label)),
}))
}
/>
</div>
</aside>

{/* 结果区域 */}
<main className="flex-1">
<div className="flex justify-between items-center mb-4">
<SearchBox placeholder="Search products..." />
<SortBy
items={[
{ label: '相关度', value: 'products' },
{ label: '价格 (从低到高)', value: 'products_price_asc' },
{ label: '价格 (从高到低)', value: 'products_price_desc' },
{ label: '评分', value: 'products_rating_desc' },
]}
/>
</div>
<Stats />
<Hits hitComponent={ProductHit} />
</main>
</div>
</InstantSearch>
);
}

// 排序需创建副本索引 (replica indices)
// products_price_asc: customRanking: ['asc(price)']
// products_price_desc: customRanking: ['desc(price)']
// products_rating_desc: customRanking: ['desc(rating)']

反模式 (Anti-patterns)

  • 模式:对非分面属性进行分面 | 原因:必须在设置中声明 attributesForFaceting | 修复:将属性添加到 attributesForFaceting 数组中
  • 模式:对隐藏过滤器未使用 filterOnly() | 原因:在不显示的属性上浪费了分面计算资源 | 修复:对不显示的过滤器使用 filterOnly(attribute)

参考资料

  • https://www.algolia.com/doc/guides/managing-results/refine-results/faceting
  • https://www.algolia.com/doc/api-reference/widgets/refinement-list/react

查询建议与自动补全 (Query Suggestions and Autocomplete)

实现带有查询建议和即时结果的自动补全。

可以使用 @algolia/autocomplete-js 实现独立自动补全,或通过 SearchBox 与 InstantSearch 集成。

查询建议需要由 Algolia 生成的独立索引。

代码示例

// 独立自动补全
// components/Autocomplete.tsx
'use client';
import { autocomplete, getAlgoliaResults } from '@algolia/autocomplete-js';
import algoliasearch from 'algoliasearch/lite';
import { useEffect, useRef } from 'react';
import '@algolia/autocomplete-theme-classic';

const searchClient = algoliasearch(
process.env.NEXT_PUBLIC_ALGOLIA_APP_ID!,
process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY!
);

export function Autocomplete() {
const containerRef = useRef<HTMLDivElement>(null);

useEffect(() => {
if (!containerRef.current) return;

const search = autocomplete({
container: containerRef.current,
placeholder: '搜索产品',
openOnFocus: true,
getSources({ query }) {
if (!query) return [];

return [
// 查询建议
{
sourceId: 'suggestions',
getItems() {
return getAlgoliaResults({
searchClient,
queries: [
{
indexName: 'products_query_suggestions',
query,
params: { hitsPerPage: 5 },
},
],
});
},
templates: {
header() {
return '建议';
},
item({ item, html }) {
return html<span>${item.query}</span>;
},
},
},
// 即时结果
{
sourceId: 'products',
getItems() {
return getAlgoliaResults({
searchClient,
queries: [
{
indexName: 'products',
query,
params: { hitsPerPage: 8 },
},
],
});
},
templates: {
header() {
return '产品';
},
i
tem({ item, html }) {
return html
<a href="/products/${item.objectID}">
<img src="${item.image}" alt="${item.name}" />
<span>${item.name}</span>
<span>$${item.price}</span>
</a>
;
},
},
onSelect({ item, setQuery, refresh }) {
// 选择后跳转
window.location.href = /products/${item.objectID};
},
},
];
},
});

return () => search.destroy();
}, []);

return <div ref={containerRef} />;
}

// 与 InstantSearch 结合使用
import { connectSearchBox } from 'react-instantsearch';
import { autocomplete } from '@algolia/autocomplete-js';

// 或使用内置的 Autocomplete 组件
import { Autocomplete as AlgoliaAutocomplete } from 'react-instantsearch';

export function SearchWithAutocomplete() {
return (
<InstantSearch searchClient={searchClient} indexName="products">
<AlgoliaAutocomplete
placeholder="搜索产品..."
detachedMediaQuery="(max-width: 768px)"
/>
<Hits hitComponent={ProductHit} />
</InstantSearch>
);
}

反模式 (Anti-patterns)

  • 模式:创建不带防抖的自动补全 | 原因:每次按键都会触发搜索,浪费操作额度 | 修复:Algolia autocomplete 自动处理防抖
  • 模式:未使用 Query Suggestions 索引 | 原因:缺失热门查询的搜索分析 | 修复:在 Algolia 控制面板中启用 Query Suggestions

参考资料

  • https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete
  • https://www.algolia.com/doc/guides/building-search-ui/ui-and-ux-patterns/query-suggestions/how-to/optimizing-query-suggestions-relevance/js

潜在坑点 (Sharp Edges)

前端代码中出现 Admin API Key

严重程度:CRITICAL (极高)

索引速率限制与节流 (Throttling)

严重程度:HIGH (高)

记录大小与索引限制

严重程度:MEDIUM (中)

网络请求中可见索引名称包含 PII (个人可识别信息)

严重程度:MEDIUM (中)

可搜索属性的顺序影响相关性

严重程度:MEDIUM (中)

全量重新索引会消耗所有操作额度

严重程度:MEDIUM (中)

每次按键都被计为一次搜索操作

严重程度:MEDIUM (中)

InstantSearch 的 SSR 注水 (Hydration) 不匹配

严重程度:MEDIUM (中)

用于排序的副本索引 (Replica Indices) 会增加存储开销

严重程度:LOW (低)

分面搜索 (Faceting) 需要声明 attributesForFaceting

严重程度:MEDIUM (中)

验证检查 (Validation Checks)

客户端代码中包含 Admin API Key

严重程度:ERROR

Admin API key 绝不能暴露在客户端代码中

提示信息:Admin API key 暴露在客户端。请使用仅限搜索 (search-only) 的 key。

硬编码 Algolia API Key

严重程度:ERROR

API key 应使用环境变量

提示信息:Algolia 凭据被硬编码。请使用环境变量。

使用搜索 Key 进行索引

严重程度:ERROR

索引操作需要 admin key,而非 search key

提示信息:索引操作使用了搜索 key。请在写入操作中使用 admin key。

在循环中进行单条记录索引

严重程度:WARNING

应将记录批量处理以提高索引效率

提示信息:循环中存在单条记录索引。请使用 saveObjects 进行批量索引。

使用 deleteBy 进行删除

严重程度:WARNING

deleteBy 成本较高且有速率限制

提示信息:deleteBy 成本较高。建议使用带有具体 ID 的 deleteObjects。

频繁的全量重新索引

严重程度:WARNING

全量重新索引会对未更改的数据浪费操作额度

提示信息:全量重新索引过于频繁。请考虑对未更改的数据进行增量同步。

使用完整客户端而非轻量版

严重程度:INFO

在前端使用轻量级客户端以减小 bundle 体积

消息:导入了完整的 Algolia 客户端。前端请使用 algoliasearch/lite。

在 Next.js 中使用常规 InstantSearch

严重程度:WARNING

使用 react-instantsearch-nextjs 以支持 SSR

消息:正在使用常规 InstantSearch。Next.js SSR 请使用 InstantSearchNext。

缺失可搜索属性配置

严重程度:WARNING

配置 searchableAttributes 以提高相关性

消息:未配置 searchableAttributes。请设置属性优先级以优化相关性。

缺失自定义排序

严重程度:INFO

自定义排序可提升业务相关性

消息:未配置 customRanking。请添加业务指标(如流行度、评分)。

协作

委派触发条件

  • 用户需要电商结账 $\rightarrow$ stripe-integration(产品搜索引导至购买)
  • 用户需要搜索分析 $\rightarrow$ segment-cdp(追踪搜索查询和结果)
  • 用户需要用户认证 $\rightarrow$ clerk-auth(为每个用户提供安全的 API 密钥)
  • 用户需要数据库设置 $\rightarrow$ postgres-wizard(索引的源数据)
  • 用户需要 Serverless 部署 $\rightarrow$ aws-serverless(用于索引任务的 Lambda)

使用场景

  • 用户提到或暗示:添加搜索功能
  • 用户提到或暗示:algolia
  • 用户提到或暗示:instantsearch
  • 用户提到或暗示:搜索 API
  • 用户提到或暗示:搜索功能
  • 用户提到或暗示:typeahead(类型前瞻)
  • 用户提到或暗示:自动补全搜索
  • 用户提到或暗示:分面搜索 (faceted search)
  • 用户提到或暗示:搜索索引
  • 用户提到或暗示:即时搜索 (search as you type)

局限性

  • 仅在任务明确符合上述范围时使用此技能。
  • 不要将输出视为针对特定环境的验证、测试或专家评审的替代方案。
  • 如果缺失必要的输入、权限、安全边界或验收标准,请停止并请求澄清。