用于文本搜索的 Mongodb 文本索引与正则表达式
在这篇文章中,我将讨论两种在 mongodb 集合中进行文本搜索的方法之间的区别,并比较它们的复杂性、优缺点。 案例研究 考虑使用帖子集合,其中每个对象都包含标题和内容: "_id": ObjectId(""), "title": "PostA", "content": "This is the content for the first post." }, { "_id": ObjectId("
在这篇文章中,我将讨论两种在 mongodb 集合中进行文本搜索的方法之间的区别,并比较它们的复杂性、优缺点。
案例研究
考虑使用帖子集合,其中每个对象都包含标题和内容:
"_id": ObjectId(""),
"title": "PostA",
"content": "This is the content for the first post."
},
{
"_id": ObjectId(""),
"title": "PostB",
"content": "This is a different content for the second post."
}
进入全屏模式 退出全屏模式
我们的目标是搜索一些文本并返回匹配的文档。
使用正则表达式
如果我们想搜索标题,使用普通的查找过滤器会很容易
db.posts.find({title: "PostA"})
如果我们确切地知道标题或使用正则表达式,如果我们知道它的一部分
db.posts.find({title: 'pattern', $options: '<options>'})
但是如果我们想在内容字段中搜索,使用这个
db.posts.find({content: "first"})
将不返回任何内容,因为它将搜索完全匹配。
所以,我们可以在这里使用正则表达式
db.posts.find({content: {$regex: /first/}})
此查询将返回 PostA 文档,因为它的内容包含单词 first。
但这将对 O(n) 进行完整的集合扫描,并且在较大的数据集上性能较差。
使用文本索引
文本索引:它将文本转换为单个单词的数组,并删除所有停用词(is、a、an 等)
让我们在内容字段上创建一个文本索引
db.posts.createIndex({content: "text"})
并且不要忘记指定“文本”以删除不需要的单词并存储关键字。
搜索一个词
db.posts.find({$text: {$search: "first"}})
这将返回 PostA。
为什么我们没有在上述查询中搜索我们的内容? 🤔
由于 mongo 将此索引视为按顺序排列的单词数组,如果您想为此文本索引添加另一个字段,例如,我们可以将标题和内容添加到索引中,它将仅在一个文本下处理它们。
例子
db.posts.createIndex({title: "text", content: "text"})
注意:当已经有另一个文本索引时,我们不能添加另一个文本索引,因此这些下一行是非法的,我们应该立即添加它们,
db.posts.createIndex({content: "text"})
db.posts.createIndex({title: "text"})
进入全屏模式 退出全屏模式
好的,现在我们有一个标题和内容的组合索引,所以如果我们使用任何关键字搜索标题或内容,它将返回正确的匹配文档。
这种方法在复杂性方面将非常有效,因为它在可用性方面也使用 indexScan ( O(log(n)) ),而不是在特定字段中搜索,这将在组合的多个字段中进行搜索,这更实用。
使用文本索引排除单词
让我们尝试搜索内容包含“post”关键字的帖子
db.posts.find({$text: {$search: "post"}})
此查询将返回 PostA 和 PostB 文档,但如果我们排除 'first' 关键字,我们只能返回 PostB:
db.posts.find({$text: {$search: "post -first"}})
这将排除内容包含“第一”一词的文档。
结论
最后我们看到使用文本索引更快,更容易,更可取,并且支持关键字排除,但是我们还有一些其他情况,当我们想要搜索子字符串或部分单词匹配时,例如 PostB 中的单词 Post 在这种情况下我们有使用正则表达式。
更多推荐
所有评论(0)