- 2020“闭关”跳槽季,啃透分布式三大技术:限流、缓存、通讯
- 腾讯一面要凉凉?线程/集合/JVM/Spring/算法问个遍,扛不住呀!
- 面试败给微服务?别怕,我带w | Q你一起手撕Dubbo,SpringBoot与Cloud
为什么要有索引??
查询快! 查询快! 查询快!
MongoDBo = I 3的10种O 1 8 N _ 4 t J r索引?
创建索引语法:
db.<collection_name>.createIndex( <key and index type spex u h Rcification>, <options>&nbs$ 6 :p;)
我们的record Collect ( U wion存在如下document
{
\"A j N ! :_id\": ObjectId(\"570c04a4ad233577f97dc459\"),
\"score\": 1034,
\_ d r B h y O m"userId\":w N E T 123,
\"location\": { state: \"ZH\", city:R 9 } 8 0 \"ChengDu\" },
\"addr\": [
{zip: \"10036\", detail: M n / x 9 7;\"高家村五组\"},
{zip:&z T 2 vnbsp;$ q ~ | ]\"94231\", detail: \"王家镇三组701\"}
]
}
_id索引
mongodb会自动为document中的_id字段加上索引,所以能用_id查询就用_id查询
单键索引
db.records.createIndex( {` = I / s score: 1 })
复合索引
db.records.createIndex( { userId: 1,&& 6 onbsp;score: 1})
多值索引
db.records.createIndex( { \"addr.zip\": 1 })
地理空间索引
MongoDB为坐标平面查询提供了专门的索引,称为地理空间索引。这种查询a Q需要两个维度,所以参数k 1 X o P J 0是2d。
db- q w L ` p N G r.map.ensureIndex({\"gps\" :w w w 1 b { L Y \"2d\"});
gps键的值必须是某种形式的一对值:一个包含2个元素的数组或者是包含2个键的内嵌文档
{\"gps\k * v . 3 D" : 2 y c;[0,100]}
{\"gps\4 Z | g f % n b" : {\"x\" : -30 , \"y\" : 30}}
{\"gps\" :&n0 X ! a =bsp! | Y x;{\"latitude\" : -180, \"longitude\" : 180 }}
至于键名可以随意。默认情况下,f = + v ] { ( q地理空间索引假设值范围是-180~180(对经纬度来说很方便),我们同样可以使用参数来对索} 3 g - l 8 a h引进行定制,比如下面的星图
db.star.trek.ensureIndex({\"light-8 o Myears\" : \"2d[ : $ O 1 S z 1 r\"} , {\"min\" : -1000, \"max\" : * R I 3 / H g 2 71000, bits;10}, {collation: {locale: \"simple\"}});t : %
上面的bits指定的是索引精度,默认情况下2d index使用的是26位精度,在默认范围-180~180中,大约等于60cm误差,最大可以设S 3 @ i置32位精度。索引精度不影响查询精度,降低精度的优点是插入操作的处理开销较低,并且占用的空间更少。较高精度的优点是查Z G F k询扫描D v g [ L 0索引的较小部分以返回结果。
collation(排序规n : l ? + m则)允许用户为字符串比较指定特定于语言的规则,例如字母和重音符号的规则。
地理空间的查询需要$near,它需要两个目标值的数组作为参数
db.map.find({\"gps\" : {\"$near\" : [40,-73]}}).limit(10);D @ d ? [ % )
默认查100个文档,如果不D B O V /需要这么多,就应该设置一个少点的值^ ! C a以节约资源。
还可以使用
db.runComma( % vnd({geoNear : \"map\", near: [40,-73],num :r { A e k R X 10})
geL _ : - G W ooNear的方式E 0 0 J N会返回每个文档到查f 0 k Q询点的距离。7 h V $ w D
还可以查询矩形和圆形内所有的点,这个时候就要将原来的9 O v : f g O z$near换成$gP f z a ?eoWithiH P en .对于矩形要使用$box选项,它的参数是2个元素的数组,第一w 6 W w s个元素指定了左下角坐标,第二个指定了右上角坐标
db.map.find({\"gps\"&nbsA : d T i ` v Y yp;: {\"$geoWithin \" : {\"$box\q $ o" : [[1w f U [0,20],[15,30]]` = . L 9 A}}});6 + Q R @
如果要查询圆形,则要使用$center,参数变成了圆心和半径
db.map.find({\"gps\" : {\"$geoWithin? H i ~ v e h 7 \" : {\"$cenl ] ] ? ^ m K t ter\" : [[12,25],5]}}});
地理K q d / L L空间查询p ] h既可以使用平面几何,也可以使用球面几何,根据使用的查询和索引类型 ! 4 ) t T 3 X来决定。 2dsphere 索引只能支持球面几何,而 2d索引同时支持平面和球面几6 : j 7 ] D何。然而,在 2dsphere索引上使A I 用球面几何的查询将会更高j _ 8 2 I t [效和准确。
2dsphere :r J K E f E https://docs.mongodb.com/manual/coreL h c r * g K r/2dsphere/
它的应用场景可以是 查找附近a | n p y h 3 :美食,查; g @ }找附近停车场等数据。
全文索引
创建索引:
db.<cW d e F @ h xollection_name>.createIndex({<ke8 U V _ ^ A Fy>: \"h 3 I W ( f *text\"});
查询数据:
db.<collection_name>.find( { $text: { $search: \"green\" } } );
查询以及排序:
db.<colle, R E s ) $ction_name>.find(
{
\"$text\": {
. Y ` w ) B K\"$search\": \"green\"
&[ o } * 8 8 +nbsw ? ; J p r i np;}
}] $ A _ 1 p 5 ,
{
\"textScoz D ~ e Mre\": {
\"$meta\": \"textSc+ P F + o 4 Kore\"
}
}
).s) w o G F G + A Hort({
&nb- ^ 4sp; \"textScore\": {
\"$meta\":&nbs& r l ( N , D %p;\"textScore\"
}
})
注意这里$ L ] 4 n O 7 H的textScore并不是集合中的某个字段,而是mongodb9 L ^ ) {根据搜索结果计Q T L 算该条数据的分数(匹配度预告,值越大)
TTL索引
我在之前的文章讲到过这个索引,它实际上是一个具有生命周期的索引,这种索引允许为每Q & m 6 r V = N /一个文档设置一个超时时间。一个文档达到预设置的老化程度后就会被删除。
db.user_session.createIndex({\} : J M v o"up_ + I Tdated\":1},{expireAfterSeconds:60*60*24});
如果一个文档的updated字段存在并且它的值是日期类型,当服务器时间比文档的updated字段的时间晚expireAfterSeconds秒时,文档就m A ? B ^ C会被删除
db.getColle8 m = `ction(\b ^ h & w 8 * N !'user_session\').insert(
 o K $ , P; {
_id: NumberInt(1),
&nbk O X `sp; \"updated\":new Date(),
- L L s b uq 3 @ b ; r t vsername:\'lisi\'A d , o w ! !
}
);
部分索引
db.<cJ M U s mollection_naR 3 T ; B Ume>.createIndex(
{\'wechat\': 1 },
{
\"parL v 3 m v q ~ t 6tialFilterExpression\": {
\b l m $ O 0 _ 7 r"wechat\": {
\"$existsp } N\":&nH m ~ + O f rbsp;true
}
&8 v % : V nnbsp; }
}
)
上面的索引表示对存在wechat字段的文档进z & } / ] + B b行索引。部分索引仅索引集合中符合指定过滤器表达式的文档,降低了索引创建和维护的性能成本。
部分索引提供了稀疏索引功能的超集,应优先于稀疏索引使用
稀疏索引
db.addresses.createIndex( { \"xmpp_id\":&nbs| ~ 9 F Rp;1 }, { p ) 9 f;sparse:&nbsR @ H Q 8 p qp;true&i V *nbsp;}&nb8 B O +sp;)
索引不索引不包含xmpp_id字段的文档。
哈希索引
db.collection.createIndex( { _id: | 5 V % K t a;\"hashed\" })
哈希索引指按照某个字段的hash值来建立索引,目前主要用于MongoDB Shari f d R # / gded Cluster的Hash分片,hash索引只能满足字段完全匹配的查询,不能满足范围查询
后台方式创建索引
db.<colW 9 ` =lectionn ^ @ q_name>.creaV e . j 6 - a 4 tteIndex( <key and : # b Y | qindex type speJ h G 7 F F k z Acifica0 5 / ]tion>, {background: true})
建立索引即耗时也费力,还需要消耗很多资源。使用{bg s Iackground: true}选项可以使这个过程在后台完成,同时正常处理请求。要是不包括这个选项,数据库会阻塞$ $ / ; 1建立索引期间的所有请求。阻塞的做法会让索X _ 8 q引建立得更快,同时也意味着应用在此期间不能应答。即便后台进行也会对正常操% Z s 8 { Q , G作有些影响,所以最好选在无关紧要的时刻。后台创建索引也会增加负载,好在不会让服务器宕机。
不过从4.2版本开始,所有索引构建都使用优化的构建过程V $ B g,该过程仅在构建过程的开始和结束时才持有排他锁。其余的构建过程将产生交错的读写操作。如果指定该属性,MongoDB将忽略这个选项。
作者:think123
原文链接:https://j7 - ,uejin.im/post/5e854f236fb9a03c563c02ee