MongoDB 全文检索
全文检索对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。
这个过程类似于通过字典中的检索字表查字的过程。
MongoDB 在 2.6 版本以后是默认开启全文检索的,目前我用的版本是3.2.7,但是还不支持中文检索,默认支持的是英文。
假设 school集合中有以下数据:
{ "_id" : 1, "zipcode" : "63109", "students" : { "comments" : "python Robot abdc", "body" : "Humans suck" } }
{ "_id" : 2, "zipcode" : "63110", "students" : { "comments" : "python abc", "body" : "Robot leader to minions" } }
{ "_id" : 3, "zipcode" : "63109", "students" : { "comments" : "python abc", "body" : "Human leader to minions" } }
{ "_id" : 4, "zipcode" : "63109", "students" : { "comments" : "python abc", "body" : "Humans suck Robot leader to minions" } }
{ "_id" : 5, "zipcode" : "63109", "students" : { "comments" : "python abc", "body" : "Humans Robot leader to minions suck" } }
{ "_id" : 7, "zipcode" : "63109", "students" : { "comments" : "python abc", "body" : "Humans suck Robot leader to minions" } }
{ "_id" : 8, "zipcode" : "63109", "students" : { "comments" : "python abc", "body" : "Humans Robot leader to minions suck" } }
1、建立全文索引
现在我们对students字段的body子项建立全文索引
db.school.ensureIndex({'students.body' : 'text'}) 如果创建成功,出现以下信息:
2、 查询body中包含Humans的记录:
db.school.find({$text:{$search: 'Humans'}}) 结果如下:
3、查询body中包含suck的记录:
db.school.find({$text:{$search: 'suck'}}) 结果如下:
4、查询body中包含leader的记录:
db.school.find({$text:{$search: 'leader'}}) 结果如下:
取反
通过在搜索单词前加上减号'-',可以在搜索的时候,排除包含该单词的记录
5、查询body中包含Robot,但不包含Humans的记录,不包含的单词前面加 ‘-’:
db.school.find({$text:{$search: 'Robot -Humans'}}) 结果如下:
6、并列查询 用\"来实现并列查询
查询comments中包含noSql,并且body包含Humans的记录,单词前面加\"
db.school.find({$text:{$search: '\"noSql \"leader'}})
6、查看索引:
db.school.getIndexes()
可以看到,我们刚才建立的全文索引名称为‘students.body_text’
一个集合只能创建一个全文索引,每次查询只能指定一个$text查询,
我们再建立个索引看看,现在我们对students字段的comments 子项建立全文索引, 是否还让建立
db.school.ensureIndex({'students.comments' : 'text'})
建立失败,原因是已经存在一个全文索引了。
7、删除索引
db.school.dropIndex('students.body_text')
删除成功
8、现在我们对students字段的comments 和body两个子项建立全文索引
db.school.ensureIndex({'students.comments' : 'text','students.body' : 'text'})
创建成功
9、查询comments中包含python的记录:
db.school.find({$text:{$search: 'python'}})
10、查询body中包含suck的记录:
db.school.find({$text:{$search: 'suck'}})
11、查询comments中包mongodb 而body中不包含suck的记录,不包含前加 ‘-’
db.school.find({$text:{$search: 'mongodb -suck'}})
词组查询
通过用引号包含由多个单词组成的词组(“suck test”),就可以实现词组搜索
db.school.find({$text:{$search: 'test suck'}})
从结果来看,实际上是包含了test和suck的合集,test和suck 在查询条件中是或的关系,而不是与的关系。
全文索引对单个字段建立全文索引,还是对多个字段建立全文索引,查询操作语法是一样的。