特殊索引类型:全文本索引和地理空间索引
全文本索引
Mongodb为了解决使用正则表达式搜索大块文件效率低和处理语言的理解问题,支持了全文本索引,它可以非常快的进行文本搜索,就如同内置了多种语言分词机制的支持一样。
创建全文本索引
需要通过关键字"text"实现,例如一个存储文章的集合,文档字段包括"title","desc","content","author","comment"
等;
- 创建单字段全文本索引
db.COLLECTION_NAME.ensureIndex({"title":"text"})
- 创建多字段全文本索引
db.COLLECTION_NAME.ensureIndex({"title":"text","author":"text"})
- 多字段全文本索引设置字段权重
db.COLLECTION_NAME.ensureIndex({"title":"text","author":"text"},{"weights":{"title":3, "author":2}})
,那么title
字典成为其中最重要的字段; - 对文档所有字符串字段创建多字段全文本索引
db.COLLECTION_NAME.ensureIndex({"$**":"text"}
,这样不仅会对顶级的字符串字段创建索引,也会搜索嵌套文档和数组中的字符串字段,使用慎用吧; - 创建索引注意事项
- 创建全文本索引成本非常高,应该在离线状态下或者对性能没有要求时创建,因为在操作频繁的集合上创建全文本索引可能会导致Mongodb过载;
- 拥有全文本索引的集合写入性能比较差,同时全文本也会降低分片时的数据迁移速度;
- 一个集合上只能有一个全文本索引,但是全文本索引可以包含多个字段;
- 全文本索引中的字段顺序不重要,默认情况下每个字段都被同等对待,可以通过
"weights"
参数控制;索引一旦创建,就不能改变字段的权重了。
使用全文本索引
例如搜索包含关键词"ask hn"或者"ask"或者“hn”的文档
- 命令方式
db.COLLECTION_NAME.runCommand("text",{"search":"ask hn"})
- 普通查询
db.COLLECTION_NAME.find($text:{$search:"ask hn"})
- 使用全文本索引注意事项
- 全文本索引是不区分大小写的,全文本索引会使用toLower将单词变成小写;
- 全文本索引只会对字符串数据进行索引,其他数据类型会被忽略;
{"search":"ask hn"}
这样搜索相当于使用OR
连接,如果想使用精准匹配,可以改为{"search":"\"ask hn\""}
;
局部的全文本索引
通过创建复合索引缩小搜索结果的范围优化全文本搜索,例如
db.COLLECTION_NAME.ensureIndex({"author":1,"title":"text"})
就创建局部全文本索引,把搜索范围分散为多个比较小的树;
地理空间索引
Mongodb支持几种类型的地理空间索引,介绍下最常见的2dsphere索引(用于地球表面类型的地图)和2d索引(用于平面和时间连续的数据);
2dsphere索引
2dsphere使用使用GenJSON数据格式指定点、线、多边形,不同类型通过字段"type"区分
表示形式
- 点的表示
{ "name":"坐标点", "loc":{"type":"Point","coordinates":[50,2]} }
- 线的表示
"name":"线", "loc":{"type":"Line","coordinates":[[0,1],[0,2],[1,2]]} }
- 多边形的表示
"name":"多边形", "loc":{"type":"Polygon","coordinates":[[0,1],[0,2],[1,2],[2,2]]} }
观察上门3中情况,使用通过文档字段"loc"下"type"区分的,字段"loc"的嵌套字段都一样的;
创建2dshare索引
db.COLLECTION_NAME.ensureIndex({"loc":"2dsphere"})
2dsphere地理空间查询
查询时需要将查询内容指定为形如{"$geometry" : geoJsonDesc}
的GenJSON对象;另外操作符$geoWithin
表示包含关系、$geoIntersects
表示交集关系,$near
表示附近关系;列举一个找出交集关系的查询语法:
db.COLLECTION_NAME.find(
{"loc":{"$geoIntersects" :
{"$geometry":
{"type":"Polygon","coordinates":[[0,1],[0,2],[1,2]]}
}
}})
2d索引
对于以二维平面上点的方式存储的数据,可以使用 2d 索引;在MongoDB2.2版及更早之前,2d 索引是用于索引普通坐标(多个点可以用数组);
- 文档结构例如:
{ "name":"2d索引文档", "loc":[[50,2],[100,2]], }
- 创建2d索引的语句:
db.COLLECTION_NAME.ensureIndex({"loc":"2d"})
- 地理空间索引默认范围是-180~180,可以设置更大的边界,例如
db.COLLECTION_NAME.ensureIndex({"loc":"2d"},{"min":-1000,"max":1000})
- 2d索引查询,不必要带
$geometry
子对象,例如
db.COLLECTION_NAME.find({"loc":{"$near":[20,11]}})