微信扫码
添加专属顾问
我要投稿
掌握Elasticsearch与BM25,提升大数据检索效率。核心内容:1. Elasticsearch与文档检索基础2. 倒排索引的构建与原理3. BM25算法在文档排序中的应用
在当今信息大爆炸的时代,各种场景都需要在海量数据中快速找到想要的信息。Elasticsearch(ES)作为一个分布式、高可用的搜索引擎,在处理海量数据的全文检索场景下表现突出。而 BM25 又是 ES 默认使用的相关性评分算法之一,能够帮助我们从众多文档中找到“最匹配”的结果。本文将通过一个简单的示例,带你一步步理解 ES 的倒排索引机制,以及 BM25 算法如何计算出搜索结果的排序。
Elasticsearch(简称 ES)是一个分布式搜索和分析引擎,广泛应用于日志分析、全文检索、业务监控等领域。它之所以能够快速检索到海量数据中的关键信息,核心原因在于以下两点:
全文检索:与常规数据库相比,ES 更偏重于对非结构化或半结构化数据的检索。比如自然语言、日志信息等,通过分词、倒排索引和基于统计的算法,能快速从大量文本中找到最相关的文档。
在传统的关系型数据库中,如果进行模糊查询,需要遍历整张表才能找到包含关键字的字段,这样既慢又耗资源。而搜索引擎发明了一种叫做“倒排索引”的结构,极大地提高了查询速度和效率。
倒排索引的核心思路是:
这与字典(或图书索引)有些相似:
通过倒排索引,想要查找包含某个词语的文档时,直接从索引中就能定位到所有相应的文档,从而大幅度加快检索过程。
为了让你更好地理解倒排索引的构建,我们用一个极简的示例说明。假设我们有以下 3 个文档:
Doc1: "Elasticsearch is a powerful search engine"
Doc2: "Elasticsearch is used for full-text search"
Doc3: "Search engines are powerful tools"
Elasticsearch 内置的分词器(如 Standard Analyzer)会对文档进行分词,并做一些常见的文本处理(如去除大小写、去除停用词、词干提取等)。在这里,我们假设分词的结果如下:
我们把每个词语出现在哪些文档里,以什么位置存起来,就形成了一个简单的倒排索引表。示例如下:
通过这样一个简单的表,我们就能快速找到一个词在哪些文档中出现。
当用户输入查询词,比如 “powerful search” 时,Elasticsearch 的做法是:
对查询进行分词和标准化
将用户输入的查询进行同样的分词处理,得到 ["powerful", "search"]。
在倒排索引中查找
计算相关性分数(BM25)
找到的文档可能都和查询有关系,但哪一个最相关?这就需要相关性算法来评分。在 ES 中,BM25 是默认算法。
根据评分排序并返回
最后将匹配到的文档按照分值从高到低排序,并返回给用户。
BM25(Best Matching 25)是一种计算“文档与查询”匹配度的打分函数。简化后的核心公式如下:
其中:
简单来说,BM25 在考虑一个词(或查询词)的稀有程度(IDF)以及该词在文档中出现的次数(TF),再结合文档长度做了一个平衡。最后得到的分数越高,说明该文档越符合用户查询意图。
让我们基于前面的示例来做一次“powerful search”最相关文档的打分。
此处我们假设 ( k_1 = 1.2, b = 0.75 ),来演示计算过程。
令 。
其中
其中 "powerful" 的 TF = 0,所以该项为 0。计算 "search" 部分:
(为了便于对比,我们稍微修改一下,可能与上表略有细微不同;但思路一样。)
显而易见,Doc3 在这个查询场景下获得最高分,Doc1 次之,Doc2 最后。
Elasticsearch 之所以能够在海量数据中快速找到最相关的文档,主要依赖以下关键点:
首先,我们需要安装并启动Elasticsearch。以下是基本步骤:
# 下载ES 8.x版本
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.x.x-linux-x86_64.tar.gz
# 解压
tar -xzf elasticsearch-8.x.x-linux-x86_64.tar.gz
# 进入ES目录
cd elasticsearch-8.x.x/
config/elasticsearch.yml
:# 集群名称
cluster.name: my-es-cluster
# 节点名称
node.name: node-1
# 数据和日志存储路径
path.data: /path/to/data
path.logs: /path/to/logs
# 网络设置
network.host: 0.0.0.0
http.port: 9200
# 开发环境设置
discovery.type: single-node
# 启动
./bin/elasticsearch
# 检查是否启动成功
curl http://localhost:9200
让我们创建一个用于存储文章的索引:
PUT /articles
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1,
"analysis": {
"analyzer": {
"my_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"stop",
"snowball"
]
}
}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "my_analyzer",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"content": {
"type": "text",
"analyzer": "my_analyzer"
},
"author": {
"type": "keyword"
},
"publish_date": {
"type": "date"
}
}
}
}
插入一些测试文档:
POST /articles/_doc/1
{
"title": "Elasticsearch Guide",
"content": "Elasticsearch is a powerful search engine based on Lucene",
"author": "John Doe",
"publish_date": "2024-03-15"
}
POST /articles/_doc/2
{
"title": "Advanced Search Techniques",
"content": "Learn how to use BM25 algorithm for better search results",
"author": "Jane Smith",
"publish_date": "2024-03-16"
}
POST /articles/_doc/3
{
"title": "Understanding Text Analysis",
"content": "Text analysis is crucial for search engine performance",
"author": "Mike Johnson",
"publish_date": "2024-03-17"
}
GET /articles/_search
{
"query": {
"match": {
"content": "search engine"
}
}
}
GET /articles/_search
{
"query": {
"multi_match": {
"query": "search engine",
"fields": ["title", "content"]
}
}
}
GET /articles/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"content": "search"
}
}
],
"should": [
{
"match": {
"title": "elasticsearch"
}
}
],
"filter": [
{
"range": {
"publish_date": {
"gte": "2024-03-15"
}
}
}
]
}
}
}
当执行搜索请求时,ES会返回包含相关性分数的结果:
{
"took": 5,
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1.3862944,
"hits": [
{
"_index": "articles",
"_id": "1",
"_score": 1.3862944,
"_source": {
"title": "Elasticsearch Guide",
"content": "Elasticsearch is a powerful search engine based on Lucene"
}
},
{
"_index": "articles",
"_id": "2",
"_score": 0.9530659,
"_source": {
"title": "Advanced Search Techniques",
"content": "Learn how to use BM25 algorithm for better search results"
}
}
]
}
}
GET /articles/_search
{
"query": {
"script_score": {
"query": {
"match": {
"content": "search engine"
}
},
"script": {
"source": "_score * (doc['publish_date'].value.millis - 1710000000000) / 86400000"
}
}
}
}
GET /articles/_search
{
"query": {
"multi_match": {
"query": "search engine",
"fields": [
"title^3",
"content"
]
}
}
}
合理设置分片数:
使用合适的映射:
keyword
类型text
类型fields
设置多字段映射优化内存使用:
doc_values
和fielddata
优化聚合性能查询优化:
好的,我来介绍Docker化安装ES以及界面化管理工具。
version: '3'
services:
elasticsearch:
image: elasticsearch:8.11.1
container_name: elasticsearch
environment:
- discovery.type=single-node
- ES_JAVA_OPTS=-Xms512m -Xmx512m
- xpack.security.enabled=false
volumes:
- ./es/data:/usr/share/elasticsearch/data
- ./es/plugins:/usr/share/elasticsearch/plugins
ports:
- "9200:9200"
- "9300:9300"
networks:
- elastic
networks:
elastic:
driver: bridge
# 创建目录
mkdir -p ./es/data ./es/plugins
# 设置目录权限
chmod 777 ./es/data ./es/plugins
# 启动容器
docker-compose up -d
# 检查容器状态
docker ps
# 测试ES是否正常运行
curl http://localhost:9200
version: '3'
services:
elasticsearch:
# ... ES配置保持不变 ...
kibana:
image: kibana:8.11.1
container_name: kibana
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
ports:
- "5601:5601"
depends_on:
- elasticsearch
networks:
- elastic
networks:
elastic:
driver: bridge
docker-compose up -d
访问 http://localhost:5601
即可打开Kibana界面。
version: '3'
services:
elasticsearch:
# ... ES配置保持不变 ...
elasticsearch-head:
image: mobz/elasticsearch-head:5
container_name: elasticsearch-head
ports:
- "9100:9100"
networks:
- elastic
访问 http://localhost:9100
即可使用elasticsearch-head。
优点:
主要功能:
Dev Tools:
Index Management:
数据可视化:
优点:
主要功能:
集群监控:
数据浏览:
REST请求:
添加Cerebro到docker-compose.yml:
version: '3'
services:
# ... 其他服务配置 ...
cerebro:
image: lmenezes/cerebro:0.9.4
container_name: cerebro
ports:
- "9000:9000"
networks:
- elastic
优点:
主要功能:
集群管理:
索引管理:
REST API:
开发环境:
生产环境:
配置建议:
version: '3'
services:
elasticsearch:
image: elasticsearch:8.11.1
container_name: elasticsearch
environment:
- discovery.type=single-node
- ES_JAVA_OPTS=-Xms512m -Xmx512m
- xpack.security.enabled=false
volumes:
- ./es/data:/usr/share/elasticsearch/data
- ./es/plugins:/usr/share/elasticsearch/plugins
ports:
- "9200:9200"
networks:
- elastic
kibana:
image: kibana:8.11.1
container_name: kibana
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
ports:
- "5601:5601"
depends_on:
- elasticsearch
networks:
- elastic
elasticsearch-head:
image: mobz/elasticsearch-head:5
container_name: elasticsearch-head
ports:
- "9100:9100"
networks:
- elastic
networks:
elastic:
driver: bridge
使用以上配置,你可以同时拥有Kibana和Elasticsearch-head的所有功能,既可以进行复杂的数据分析和可视化,也可以快速查看集群状态和数据。
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费场景POC验证,效果验证后签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2025-03-30
下一代企业IT架构:MCP中台和软件进化
2025-03-28
RagFlow进阶|Text2SQL 优化方法明细大公开
2025-03-28
DeepSeek+Power BI实现滚动表格效果SVG
2025-03-26
GitHub星标20K!Chat2DB:用说人话的方式写SQL
2025-03-25
“显示思维链”在经济犯罪案件侦办中的应用
2025-03-24
董事长,如果今天你怕错过AI,回想下六年前是怎样怕错过数字化转型的?
2025-03-23
DeepSeek震撼出击:一份财务分析报告框架,彻底颠覆你的认知!
2025-03-23
财务人速看!5步实用DeepSeek自动生成专业分析图表,这个AI神器让你告别加班!
2024-10-14
2024-06-20
2025-02-04
2024-10-09
2024-06-14
2024-06-16
2024-06-14
2024-05-31
2024-07-24
2024-07-03
2025-03-24
2025-03-11
2025-03-10
2025-03-10
2025-02-28
2025-02-25
2025-02-22
2025-02-22