MongoDB基础学习二----MongoDB中常用的索引操作

# 索引(重点)

在任何的数据库中,索引都是一种提升数据库检索性能的手段,这一点在MongoDB数据库之中同样是存在的,
在MongoDB数据里面仍然会存在有两种的索引创建。
	|- 自动创建
	|- 手动创建

范例:重新准备一个新的集合
db.student.drop()
db.student.insert({"name" : "吴一", "sex" : "男", "age" : 19, "score" : 100, "address" : "日本"})  
db.student.insert({"name" : "孙二", "sex" : "女", "age" : 35, "score" : 80, "address" : "海南"})  
db.student.insert({"name" : "张三", "sex" : "男", "age" : 27, "score" : 70, "address" : "新加坡"})  
db.student.insert({"name" : "李四", "sex" : "男", "age" : 20, "score" : 60, "address" : "美国"})  
db.student.insert({"name" : "王五", "sex" : "女", "age" : 46, "score" : 50, "address" : "俄罗斯"})  
db.student.insert({"name" : "赵六", "sex" : "女", "age" : 58, "score" : 40, "address" : "加拿大"})  
db.student.insert({"name" : "苗七", "sex" : "男", "age" : 32, "score" : 30, "address" : "中国"})  
db.student.insert({"name" : "王八", "sex" : "男", "age" : 24, "score" : 20, "address" : "尼泊尔"})  
db.student.insert({"name" : "刘九", "sex" : "女", "age" : 37, "score" : 10, "address" : "泰国"})  
db.student.insert({"name" : "钱十", "sex" : "男", "age" : 30, "score" : 46, "address" : "越南"})  
# 此时集合中并没有去设置任何的索引,那么下面通过getIndexes()函数来观察在student集合里面已经存在的索引内容。

# 范例:查询默认状态下的student集合的索引内容
db.student.getIndexes()
# 发现存在有一个 "_id" 列的索引

# 创建自己的索引
db.集合.ensuerIndex({"列" : 1})
	|- 设置的 1 表示索引将按照升序的方式排列。如果要降序,则设置为 -1

# 范例: 创建索引,在age字段设置一个降序索引
db.student.ensureIndex({"age" : -1})
# 此时并没有设置索引的名字,索引名字是自动命名的。
# 通过 db.student.getIndexes() 来查看索引
# 命名规范: "字段名称_" + 索引的排序方式

# 范例:针对于当前的 age 字段上的索引做一个分析
db.student.find({"age" : {"$eq" : 19}}).explain()
# 此时的查询使用了索引技术
# 下面来观察下不使用索引的情况
# 范例:针对于 score 字段上查询成绩
db.student.find({"score" : {"$gt" : 60}}).explain()

# 此处省略一大部分

# 如果再一个集合中过多的使用索引,实际上会导致性能下降,那么可以删除索引
# 范例: 删除一个索引
db.student.dropIndex({"name" : -1, "score" : -1}) # 删除name字段和score字段上的索引
# 删除全部索引(并不会删除自动创建的索引)
db.student.dropIndexes();



# 唯一索引
唯一索引的主要目的是用在某一个字段上,使该字段的内容不重复。

范例1:创建唯一索引
db.student.ensureIndex({"name" : 1}, {"unique" : true})
# 在 name 字段上的内容绝对不允许重复
# 范例2:测试(在name字段不允许重复)
db.student.insert({"name" : "吴一", "sex" : "女", "age" : 39, "score" : 80, "address" : "韩国"})  
# 此时:除了name字段上的内容,所有数据都不一样,但是由于在name字段上设置了唯一索引,所以在name字段中插入重复信息,会提示以下错误
# E11000 duplicate key error collection: stu.student index: name_1 dup key



# 过期索引
# 在一些程序站点中会出现若干秒之后信息被删除的情况
# 例如:手机信息验证码,那么在 MongoDB 中可以很轻松的实现过期索引,但是时间往往不怎么准确

# 范例1:设置过期索引
db.phones.ensureIndex({"time" : 1}, {expireAfterSeconds : 10});
# 设置索引在10秒后消失

# 范例2:在一个 phones 集合里面设置过期索引
# 如果要想实现过期索引,需要保存一个时间信息
db.phones.insert({"tel" : "110", "code" : "110", "time" : new Date()})
db.phones.insert({"tel" : "111", "code" : "111", "time" : new Date()})
db.phones.insert({"tel" : "112", "code" : "112", "time" : new Date()})
db.phones.insert({"tel" : "113", "code" : "113", "time" : new Date()})
db.phones.insert({"tel" : "114", "code" : "114", "time" : new Date()})
# 等到10s以后(不会特别准确,可能需要很长时间)就会消失
# 这种特性在进行一些临时数据保存的时候非常有用



# 全文索引
# 产生背景:在一些信息平台上面经常需要进行信息模糊查询,最早的时候是利用了某个字段上实现的模糊查询,但是
# 这个时候返回的数据并不一定准确,因为只能够查A字段或者是B字段,而在MongoDB里面实现了非常简单的全文检索

# 范例: 定义一个新的集合
db.news.insert({"title" : "A", "content" : "B"});
db.news.insert({"title" : "C", "content" : "D"});
db.news.insert({"title" : "B", "content" : "C"});
db.news.insert({"title" : "D", "content" : "A"});
db.news.insert({"title" : "java", "content" : "C++"});

# 范例:设置全文检索
db.news.ensureIndex({"title" : "text", "content" : "text"})

# 实现数据的模糊查询
	|- 如果要想表示出全文检索,则使用 "$text" 判断符,而要想进行数据的查询,则使用 "$search" 运算符
		|- 查询指定关键字:{"$search" : "查询关键字"};
		|- 查询多个关键字(或关系): {"$search" : "查询关键字 查询关键字 查询关键字 查询关键字 ..."}
		|- 查询多个关键字(与关系): {"$search" : "\"查询关键字\"\"查询关键字\"..."}
		|- 查询多个关键字(排除某一个): {"$search" : "\"查询关键字\"\"查询关键字\"...-排除关键字"}

# 范例1:查询单个内容
db.news.find({"$text" : {"$search" : "D"}});
# 范例2:查找包含有 B 和 C 的内容(或关系)
db.news.find({"$text" : {"$search" : "B C"}});
# 范例3:同时包含有 B 和 C 的内容(与关系) 
db.news.find({"$text" : {"$search" : "\"B\"\"C\""}});
# 包含有 B 但是没有 C 的内容(排除某一个)
db.news.find({"$text" : {"$search" : "\"B\"-C"}});

# 在进行全文检索的时候,还可以使用相似度的打分来判断检索结果。
# 范例5:为结果打分(分越高越好, 因为越高查询结果越准确)
db.news.find({"$text" : {"$search" : "B"}}, {"score" : {"$meta" : "textScore"}});
# 范例6:按 score 进行降序排序
db.news.find({"$text" : {"$search" : "C"}}, {"score" : {"$meta" : "textScore"}}).sort({"score" : {"$meta" : "textScore"}}).pretty();
# 按照打分的成绩进行排序,实际上就可以实现更加准确的信息搜索

# 但是还有一个小错误:如果一个数据的字段太多了,那么每个字段都设置全文检索就会非常麻烦。
# 所以,为所有字段设置全文检索应运而生
# 范例7:为所有字段设置全文检索
db.news.ensureIndex({"$**" : "text"});
# 这是一种最简单的设置全文索引的方式,不过最好不要使用,因为索引越多操作越慢



# 地理信息索引
# 分为两类
	|- 2D 平面索引(应用范例 :陌陌 摇一摇查找附近的人)
	|- 2DSphere 球面索引
在 2D 索引中,能够保存的其实就是坐标,而且坐标保存的就是经纬度的坐标

# 范例1:定义一个商铺集合
db.shop.insert({"loc" : [10, 10]});
db.shop.insert({"loc" : [10, 11]});
db.shop.insert({"loc" : [11, 10]});
db.shop.insert({"loc" : [12, 15]});
db.shop.insert({"loc" : [120, 130]});
db.shop.insert({"loc" : [90, 90]});
db.shop.insert({"loc" : [16, 17]});

# 范例2: 为 shop 的集合做一个 2D 的索引
db.shop.ensureIndex({"loc" : "2d"});
# 这个时候shop集合就可以实现坐标位置的查询了,而要进行查询的话有两种方式
	|- "$near" 查询,查询举例某个点最近的坐标点
	|- "$geoWithin" 查询, 查询某个形状内的点
# 范例3:假设我现在的坐标为 [11, 11], 查询离我现在位置近的点
db.shop.find({"loc" : {"$near" : [11, 11]}});
# 如果执行了上述查询,实际上会将数据集合里面的前100个点都返回来了,可是有的距离太远了,所以设置查询的距离范围
# 范例4:设置查询距离范围,查询距离最近的4个点
db.shop.find({"loc" : {"$near" : [11, 11], "$maxDistance" : 5}});
# 在2D索引里面,虽然支持最大距离,但是不支持最小距离。
# 但是可以设置一个查询的范围, 使用 "$geoWithin" 查询,也可以设置的范围如下
	|- 矩形范围($box) {"$box" : [[x1, y1], [x2, y2]]};
	|- 圆形范围($center) {"$center" : [[x1, y1], r]};
	|- 多边形 ($polygon) {"polygon" : [[x1, y1], [x2, y2], [x3, y3], ...]}
# 范例5:查询矩形
db.shop.find({"loc" : {"$geoWithin" : {"$box" : [[9, 9], [11, 11]]}}});
# 范例6:查询圆形
db.shop.find({"loc" : {"$geoWithin" : {"$center" : [[11, 11], 3]}}});



# 在 MongoDB 数据库中,除了做一些支持的操作函数之外,还有一个重要的命令:runCommand(),这个命令可以执行所有的特定的 MongoDB 命令
# 范例7:利用 runCommand() 实现信息查询
db.runCommand({"geoNear" : "shop", near : [10, 10], maxDistance : 5, num : 2});
# 在shop中找到距离near这个位置最近的5个位置,只返回两个

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值