数据操作前,需要先开启MongoDB服务,并建立链接。
开启服务
mongod
建立链接
mongo
先对集合增加200万条记录,用于查询使用。
demo5.js
//生成随机数
function GetRandomNum(min, max) {
let range = max - min; //得到随机数区间
let rand = Math.random(); //得到随机值
return (min + Math.round(rand * range)); //最小值+随机数取整
}
//生成随机用户名
function GetRadomUserName(min, max) {
let tempStringArray = "123456789qwertyuiopasdfghjklzxcvbnm".split(""); //构造生成时的字母库数组
let outPuttext = ""; //最后输出的变量
//进行循环,随机生产用户名的长度,这里需要生成随机数方法的配合
for (let i = 1; i < GetRandomNum(min, max); i++) {
//随机抽取字母,拼装成需要的用户名
outPuttext = outPuttext + tempStringArray[GetRandomNum(0, tempStringArray.length)]
}
return outPuttext;
}
var db = connect('company');
db.randomInfo.drop();
var tempInfo = [];
for (let i = 0; i < 2000000; i++) {
tempInfo.push({
username: GetRadomUserName(7, 16),
regeditTime: new Date(),
randNum0: GetRandomNum(100000, 999999),
randNum1: GetRandomNum(100000, 999999),
randNum2: GetRandomNum(100000, 999999),
randNum3: GetRandomNum(100000, 999999),
randNum4: GetRandomNum(100000, 999999),
randNum5: GetRandomNum(100000, 999999),
randNum6: GetRandomNum(100000, 999999),
randNum7: GetRandomNum(100000, 999999),
randNum8: GetRandomNum(100000, 999999),
randNum9: GetRandomNum(100000, 999999),
})
}
db.randomInfo.insert(tempInfo);
在vscode终端中执行 load('./demo5.js') 即可将上面的数据插入到数据库名称为company,名称为randomInfo的集合中。
实例一:查询username为c52cce的记录(未添加索引)
demo6.js
var startTime = new Date().getTime();
var db = connect('company');
var rs = db.randomInfo.find({ username: 'c52cce' });
rs.forEach(rs => { printjson(rs) });
var runTime = new Date().getTime() - startTime;
print('执行了' + runTime + 'ms');
执行结果:
在不加索引的情况下,时间消耗一秒左右。
先查询下集合中的索引情况:
db.randomInfo.getIndexes()
可以看到默认有一条索引,是_id字段,这个索引是数据库默认自带的,不过一般不用,因为_id字段的值是数据库自己生成的,没有规律。
为username字段添加索引:
db.randomInfo.ensureIndex({ username: 1 })
索引添加完成后查询下最新的索引情况:
实例二:查询username为c52cce的记录(username字段有索引)
还是原来的查询语句,加上索引只要5毫秒。
总结:无论是在关系型数据库还是文档数据库,建立索引都是非常重要的。索引这东西是要消耗硬盘和内存资源的,所以还是要根据程序需要进行建立了。MongoDB也进行了限制,集合中索引不能超过64个。
复合索引
复合索引就是两条以上的索引。已经把username字段建立了索引,现在把randNum0,这个字段添加索引。
db.randomInfo.ensureIndex({randNum0:1})
两个索引同时查询:
var startTime = new Date().getTime();
var db = connect('company');
var rs = db.randomInfo.find({ username: '2ocny9sky7hf', randNum0: 344600 });
rs.forEach(rs => { printjson(rs) });
var runTime = new Date().getTime() - startTime;
print('执行了' + runTime + 'ms');
执行结果:
从性能上看并没有什么特殊的变化,查询时间还是在4ms左右。MongoDB的复合查询是按照索引顺序进行查询的。就是用db.randomInfo.getIndexes()查询出的数组。
指定索引查询(hint)
数字的索引要比字符串的索引快,这就需要一个方法来打破索引表的查询顺序,用我们自己指定的索引优先查询,这个方法就是hint()
var startTime = new Date().getTime();
var db = connect('company');
var rs = db.randomInfo.find({ username: '2ocny9sky7hf', randNum0: 344600 }).hint({ randNum0: 1 });
rs.forEach(rs => { printjson(rs) });
var runTime = new Date().getTime() - startTime;
print('执行了' + runTime + 'ms');
执行结果:
虽然指定了使用数字类型字段所为索引查询,但查询时间没有太大区别,因为数据量还不够大。
全文索引
插入测试数据
db.info.insert({contextInfo:"I am a programmer, I love life, love family. Every day after work, I write a diary."})
db.info.insert({contextInfo:"I am a programmer, I love PlayGame, love drink. Every day after work, I playGame and drink."})
创建全文索引
db.info.ensureIndex({contextInfo:'text'})
text关键词来代表全文索引
使用全文索引
db.info.find({$text:{$search:"programmer"}})
$text:表示要在全文索引中查东西。
$search:后边跟查找的内容。
删除索引
当索引性能不佳或起不到作用时,需要删除索引,删除索引的命令是dropIndex()
删除之前先查询下索引:
现在要删除randNum0字段上面的索引,语句如下:
db.randomInfo.dropIndex('randNum0_1')
执行结果:
这里需要注意的是,删除索引时,参数为索引的name,而不是key。
更多索引操作参考文章:http://jspang.com/detailed?id=36