首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >MongoDB 全文索引 与 展示查询数据的一部分,提高性能

MongoDB 全文索引 与 展示查询数据的一部分,提高性能

作者头像
AustinDatabases
发布2026-06-26 20:19:03
发布2026-06-26 20:19:03
50
举报
文章被收录于专栏:AustinDatabasesAustinDatabases

MongoDB 到底支持不支持全文索引,回答是支持,但是怎么使用,使用中有什么问题,为什么有的人说,或者谣传,使用MongoDB 的全文索引后,还是要使用ES。

今天我们说说这个事情,首先我们要确认一点MongoDB 自 2.4 版本(2013年)引入全文索引实验性支持,并于 2.6 版本(2014年)正式将其作为核心功能内置并默认开启。无论是 MongoDB 7.0 还是最新的 8.0 版本,均原生、完整地支持本地自建环境下的全文索引(Text Index)功能。用户无需依赖任何外部组件,即可直接在自建集群中创建和检索文本索引。

第一,一个集合只能拥有一个全文索引,在多个字段的情况下,全文索引可以覆盖多个字段,将这些KEY VALUE 放入到一个全文索引中。在创建全文索引会对文本进行分词,最后一个事情就是,写性能的损耗,全文索引的底层数据结构相对复杂,其构建和更新的开销高于普通的B-TREE的单字段索引,因此在高频写入的场合要谨慎操作。

代码语言:javascript
复制

test_search_db> db.articles.drop();
true
test_search_db> 

test_search_db> print("开始生成 10 万条数据,请稍候...");
| 
| const totalRecords = 100000;
| const batchSize = 5000; // 每 5000 条数据批量提交一次
| let bulk = db.articles.initializeUnorderedBulkOp();
| 
| // 词库:用于随机组合生成文本
| const keywords = ["MongoDB", "Database", "AI", "Cloud", "Performance", "Index", "Query", "Optimization", "Full-text Search", "Developer", "Java", "Python", "Node.js", "Cluster", "Scaling", "Big Data", "Analytics"];
| const verbs = ["improves", "accelerates", "transforms", "simplifies", "manages", "secures", "analyzes", "powers"];
| const readyText = ["This article explores the advanced features of modern technologies.", "A deep dive into indexing strategies and best practices.", "How to build scalable applications with high availability.", "An introductory guide for developers and architects."];
| 
| function getRandomElement(arr) {
|     return arr[Math.floor(Math.random() * arr.length)];
| }
| 
| function generateRandomString(wordCount) {
|     let sentence = [];
|     for (let i = 0; i < wordCount; i++) {
|         sentence.push(getRandomElement(keywords));
|         if (i % 3 === 0 && i > 0) sentence.push(getRandomElement(verbs));
|     }
|     return sentence.join(" ") + ". " + getRandomElement(readyText);
| }
| 
| // 3. 循环生成并分批插入
| for (let i = 1; i <= totalRecords; i++) {
|     // 随机生成标题、摘要和正文,确保里面包含我们要搜索的关键词
|     let title = `${getRandomElement(keywords)}${getRandomElement(verbs)}${getRandomElement(keywords)}`;
|     let summary = generateRandomString(8);
|     let content = generateRandomString(30); // 正文较长
| 
|     bulk.insert({
|         article_id: i,
|         title: title,
|         summary: summary,
|         content: content,
|         views: Math.floor(Math.random() * 10000),
|         createdAt: new Date(Date.now() - Math.floor(Math.random() * 10000000000))
|     });
| 
|     // 达到批次大小,执行写入并重置 bulk
|     if (i % batchSize === 0) {
|         bulk.execute();
|         bulk = db.articles.initializeUnorderedBulkOp();
|         print(`已写入 ${i} 条数据...`);
|     }
| }
| 
| // 检查是否有剩余未提交的数据
| if (totalRecords % batchSize !== 0) {
|     bulk.execute();
| }
| 
| print("数据填充完毕!当前总数据量:", db.articles.countDocuments());
开始生成 10 万条数据,请稍候...
已写入 5000 条数据...
已写入 10000 条数据...
已写入 15000 条数据...
已写入 20000 条数据...
已写入 25000 条数据...
已写入 30000 条数据...
已写入 35000 条数据...
已写入 40000 条数据...
已写入 45000 条数据...
已写入 50000 条数据...
已写入 55000 条数据...
已写入 60000 条数据...
已写入 65000 条数据...
已写入 70000 条数据...
已写入 75000 条数据...
已写入 80000 条数据...
已写入 85000 条数据...
已写入 90000 条数据...
已写入 95000 条数据...
已写入 100000 条数据...
数据填充完毕!当前总数据量: 100000

在插入完数据后,我们需要针对数据进行验证和创建索引。

代码语言:javascript
复制
test_search_db> show collections;
articles
test_search_db> db.articles.find().limit(1);
[
  {
    _id: ObjectId('69fe22f484970425839df8a3'),
    article_id: 1,
    title: 'Analytics manages Index',
    summary: 'Java Node.js Optimization Index transforms Database Cloud Performance manages Python. An introductory guide for developers and architects.',
    content: 'Database Python Query Cloud simplifies Java Python AI analyzes Scaling AI Analytics improves Python Database Developer powers Performance Node.js Database improves Java Full-text Search Java improves Index Scaling Performance transforms Node.js Analytics Cloud improves Full-text Search Query Cluster simplifies Index Node.js. A deep dive into indexing strategies and best practices.',
    views: 5895,
    createdAt: ISODate('2026-02-11T17:30:28.608Z')
  }
]

通过全文索引进行数据的查询

代码语言:javascript
复制
test_search_db> db.articles.createIndex({ content: "text" });
content_text
test_search_db> db.articles.find(
|   { $text: { $search: "Database" } }
| ).limit(10);
[
  {
    _id: ObjectId('69fe231e84970425839ec463'),
    article_id: 52161,
    title: 'Performance analyzes Cloud',
    summary: 'AI Analytics Index Optimization analyzes Query Query Developer simplifies Index. An introductory guide for developers and architects.',
    content: 'Query Python Database Full-text Search accelerates Query Cluster Cluster manages Performance Developer Developer simplifies Database Database Full-text Search transforms Database Developer Query accelerates Database Analytics Index powers Java Database Python powers Database Database Database transforms Developer Performance Database improves Database Index. How to build scalable applications with high availability.',
    views: 4930,
    createdAt: ISODate('2026-05-01T16:06:04.940Z')
  },

通过查看执行计划,发现当前的查询走了相关的全文索引

通过查看执行计划,发现当前的查询走了相关的全文索引。

那么如果是多字段的情况,针对一个表只能有一个全文索引的情况下,我们先删除,在进行后续的添加。

db.articles.find( |text: { search: searchKeyword } },{ title: 1, summary: 1, content: 1, score: {

} ).sort( { score: { $meta: "textScore" } } |).limit(5).explain("executionStats").executionStats;

数据库查询执行计划

实际上MongoDB的全文索引使用 $test + TextIndex 倒排索引来完成的,建立全文索引可以针对一个key value也可以针对多个key value进行,

代码语言:javascript
复制
db.articles.createIndex({
  title: "text",
  summary: "text",
  content: "text"
}, {
  weights: {
    title: 10,
    summary: 3,
    content: 1
  },
  name: "ArticleTextIndex"
})

在针对多个key value进行全文索引查询的时候,可以给每个字段权重,通过权重来指定那些key value更能代表出每个查询可以过滤的采样率。

而当全文索引查询时,如果我们要展示出查询的信息,可以做预先展示,也就是查询的数据只对全文索引命中的部分,展示一小段数据如下,我们在preview 里面将要展示的内容进行截取,只展示前20个字符,通过降低展示的数据,提高数据查询的性能。

代码语言:javascript
复制
db.articles.find(
  { $text: { $search: searchKeyword } },
  {
    title: 1,
    summary: 1,
    preview: { $substrCP: ["$content", 0, 20] },
    score: { $meta: "textScore" },
    _id: 0
  }
)
.sort({ score: { $meta: "textScore" } })
.limit(10);

查询数据preview

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-06-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AustinDatabases 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档