跳到主要内容

搜索引擎

问题

Elasticsearch 的核心原理是什么?如何实现全文搜索?

答案

倒排索引

传统数据库是「文档 → 词」的映射,倒排索引是「词 → 文档」的映射。

// 正排索引(MySQL)
Doc1: "React 性能优化指南"
Doc2: "Vue 性能对比分析"

// 倒排索引(Elasticsearch)
"React" → [Doc1]
"Vue" → [Doc2]
"性能" → [Doc1, Doc2]
"优化" → [Doc1]
"分析" → [Doc2]

搜索「性能」时,直接从倒排索引找到 [Doc1, Doc2],无需全表扫描。

Elasticsearch 基础操作

elasticsearch.ts
import { Client } from '@elastic/elasticsearch';

const es = new Client({ node: 'http://localhost:9200' });

// 创建索引(定义 Mapping)
await es.indices.create({
index: 'articles',
body: {
mappings: {
properties: {
title: { type: 'text', analyzer: 'ik_max_word' }, // 中文分词
content: { type: 'text', analyzer: 'ik_smart' },
tags: { type: 'keyword' }, // 不分词,用于精确匹配
publishedAt: { type: 'date' },
},
},
},
});

// 索引文档
await es.index({
index: 'articles',
body: {
title: 'React 18 新特性解析',
content: 'React 18 引入了并发渲染...',
tags: ['react', 'frontend'],
publishedAt: '2024-01-01',
},
});

// 全文搜索
const result = await es.search({
index: 'articles',
body: {
query: {
multi_match: {
query: 'React 性能',
fields: ['title^2', 'content'], // title 权重是 content 的 2 倍
},
},
highlight: {
fields: { title: {}, content: {} }, // 高亮匹配词
},
},
});

轻量替代方案

方案特点适用场景
Elasticsearch功能强大、分布式大规模全文搜索
Meilisearch简单易用、即时搜索中小应用、搜索即服务
Typesense低延迟实时搜索补全
PostgreSQL 全文搜索内置、无额外依赖简单搜索需求
meilisearch.ts
// Meilisearch(更简单的替代方案)
import { MeiliSearch } from 'meilisearch';

const client = new MeiliSearch({ host: 'http://localhost:7700', apiKey: 'xxx' });

// 添加文档
await client.index('articles').addDocuments(articles);

// 搜索(自动处理拼写纠错、同义词)
const results = await client.index('articles').search('React 性能', {
limit: 10,
attributesToHighlight: ['title', 'content'],
});

常见面试问题

Q1: Elasticsearch 和 MySQL LIKE 的区别?

答案

维度ESMySQL LIKE
原理倒排索引全表扫描
中文分词后搜索模糊匹配
性能亿级数据毫秒返回百万级就很慢
相关性自动评分排序

Q2: 分词器是什么?

答案

分词器将文本切分为词条(Term)。如「React 性能优化」:

  • 标准分词器react(按字切分)
  • IK 分词器(中文):react性能优化(按语义切分)

Q3: ES 如何保证和数据库的数据一致?

答案

  1. 双写:写数据库的同时写 ES(有一致性风险)
  2. CDC(Change Data Capture):监听 MySQL Binlog 同步到 ES(推荐)
  3. 消息队列:写数据库后发消息,消费者写 ES

相关链接