在这篇文章中,我将讨论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文档,因为其内容包含第一个单词。
但这将进行O(n)的完整集合扫描,并且在较大的数据集上的性能较差。
使用文本索引
文本索引:它将文本转换为单个单词数组,并删除所有停止单词(is,a,an et et et et et et et ef)
让我们在我们的内容字段上创建文本索引
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))),而不是在特定字段中进行搜索,这将在更实用的组合多个字段中搜索。
使用文本索引排除单词
让我们尝试搜索带有内容的帖子包含“帖子”关键字
db.posts.find({$text: {$search: "post"}})
此查询将同时返回PostA和Postb文档,但是如果我们排除“第一个”关键字:
,我们只能返回Postb
db.posts.find({$text: {$search: "post -first"}})
这将排除具有“ first”一词的内容。
结论
最后,我们看到使用文本索引更快,更容易,更可取,可以使用关键字排除,但是当我们想搜索substring或partial Word匹配时,我们还有其他一些情况,例如Postb中的postb中的单词post案例我们必须使用正直。