# 使用mongodb

在命令窗口输入mongo进入mongo语法

  1. show dbs

展示所有数据库

  1. db

查看当前数据库

  1. db.version()

查看数据库版本

  1. use xxx

使用选定的数据库,如果没有即为创建新的数据库

  1. show collections

显示数据库中的集合

  1. db.xxx.insert()

新建数据集合和插入文件(数据),当集合没有时,这时候就可以新建一个集合,并向里边插入数据。Demo:db.user.insert({"name":"apple"})

//批量插入
db.test.insert([
    {"_id":1},
    {"_id":2},
    {"_id":3}
])
  1. db.xxx.find()

查询所有数据,这条命令会列出集合下的所有数据,可以看到MongoDB是自动给我们加入了索引值的。

  • 没有加参数即为查找全部
  • db.student.find({"score.shuxue":70});精确匹配
  • db.student.find({"score.shuxue":70 , "age":12})多个条件
  • db.student.find({"score.yuwen":{$gt:50}});大于条件
  • db.student.find({$or:[{"age":9},{"age":11}]});或者。寻找所有年龄是9岁,或者11岁的学生
  • db.restaurants.find().sort( { "borough": 1, "address.zipcode": 1 } )打点调用sort,表示升降排序
  1. db.xxx.findOne()

查询第一个符合要求的文件数据eg:db.user.findOne({name:"apple",age:18})

  1. update

更新

  • db.student.update({"name":"小明"},{$set:{"age":16}});查找第一个名字叫做小明的,把年龄更改为16岁 $set 更改局部
  • db.student.update({"sex":"男"},{$set:{"age":33}},{multi: true});更改所有符合的,如果不加multi,只会默认修改第一条符合的数据
  • db.student.update({"name":"小明"},{"name":"大明","age":16});完整替换,不出现$set关键字了:
  • db.workmate.update({"name":"MinJie"},{$unset:{"age":''}}); $unset 用于将key删除
  • db.workmate.update({"name":"MinJie"},{$inc:{"age":-2}});它是对value值的修改,但是修改的必须是数字,字符串是不起效果的。我们现在要对MiJie的年龄减去2岁,就可以直接用 $inc 来操作。
  • db.workmate.update({name:'xiaoWang'},{$set:{age:20}},{upsert:true}); upsert 是在找不到值的情况下,直接插入这条数据。true代表没有就添加,false代表没有不添加(默认值)。
  • update数组修改器
//$push:给小王加上一个爱好(interset)为draw,interest就是个数组 
db.workmate.update({name:'xiaoWang'},{$push:{interest:'draw'}})
//$ne:检查一个值是否存在,如果不存在再执行操作,存在就不执行
//如果xiaoWang的爱好(interest)里没有palyGame这个值,我们就加入Game这个爱好
db.workmate.update({name:'xiaoWang',"interest":{$ne:'playGame'}},{$push:{interest:'Game'}})
//$addToSet 升级版的$ne
//小王(xiaoWang)兴趣(interest)中有没有阅读(readBook)这项,没有则加入读书(readBook)的兴趣.
db.workmate.update({name:"xiaoWang"},{$addToSet:{interest:"readBook"}})
//$each 批量追加 它可以传入一个数组,一次增加多个值进去,相当于批量操作,性能同样比循环操作要好很多
//一次加入三个爱好,唱歌(Sing),跳舞(Dance),编码(Code)
var newInterset=["Sing","Dance","Code"];
db.workmate.update({name:"xiaoWang"},{$addToSet:{interest:{$each:newInterset}}})
//$pop 删除数组值$pop只删除一次,并不是删除所有数组中的值。而且它有两个选项,一个是1和-1。
//1:从数组末端进行删除  -1:从数组开端进行删除
db.workmate.update({name:'xiaoWang'},{$pop:{interest:1}})
//定位修改
//只知道修改数组的第几位,但并不知道是什么,这时候我们可以使用interest.int 的形式
//修改xiaoWang的第三个兴趣
db.workmate.update({name:'xiaoWang'},{$set:{"interest.2":"马克杯"}})
  1. remove

删除文件数据,注意的是要跟一个条件。Demo:db.user.remove({name:"jspang"})使用justone选项将删除操作仅限于一个匹配的文档。db.restaurants.remove( { "borough": "Queens" }, { justOne: true } )

  1. drop

db.xxx.drop(),删除整个集合,慎用!

  1. dropDatabase()

删除整个数据库!!!

  1. mongoimport --db test --collection restaurants --drop --file primer-dataset.json

数据导入数据库

  • -db test 想往哪个数据库里面导入
  • --collection restaurants 想往哪个集合中导入
  • --drop 把集合清空
  • --file primer-dataset.json 哪个文件
  1. delete

remove() 方法已经过时了,现在官方推荐使用 deleteOne() 和 deleteMany() 方法。

//删除集合下全部文档:
db.inventory.deleteMany({})
//删除 status 等于 A 的全部文档:
db.inventory.deleteMany({ status : "A" })
//删除 status 等于 D 的一个文档:
db.inventory.deleteOne( { status: "D" } )

# 写入数据和性能问题

如果在循环插入和批量插入举起不定,那就选批量插入吧,它会给我们更优的性能体验

// var startTime = (new Date()).getTime(); //得到开始时间
// var  db = connect('log');  //链接数据库
// //开始循环
// for(let i=0;i<1000;i++){
//     db.test.insert({num:i});
// }
//  
// var runTime = (new Date()).getTime()-startTime;//计算时间差
// print ('This run this is:'+runTime+'ms');//打印出来
//700ms

var startTime = (new Date()).getTime();
var  db = connect('log');
 
 
var tempArray = []              //声明一个数组
for(let i=1001;i<2000;i++){        //循环向数组中放入值
    tempArray.push({num:i});
}
db.test.insert(tempArray)       //批量一次插入
 
var runTime = (new Date()).getTime()-startTime;
print ('This run this is:'+runTime+'ms');
//30ms

# 状态返回与安全

db.runCommand():
db.workmate.update({sex:1},{$set:{money:1000}},false,true)
var resultMessage=db.runCommand({getLastError:1})
printjson(resultMessage);
{
	"connectionId" : 1,
	"updatedExisting" : true,
	"n" : 2,
	"syncMillis" : 0,
	"writtenTo" : null,
	"err" : null,
	"ok" : 1
}
//ok==1即为成功
findAndModify
var myModify={
    findAndModify:"workmate",
    query:{name:'JSPang'},
    update:{$set:{age:18}},
    new:true    //更新完成,需要查看结果,如果为false不进行查看结果
}
var ResultMessage=db.runCommand(myModify);
 
printjson(ResultMessage)
{
	"lastErrorObject" : {
			"n" : 1,
			"updatedExisting" : true
	},
	"value" : {
			"_id" : ObjectId("5d3ffa8a9ed934af890507d9"),
			"name" : "JSPang",
			"age" : 18,
			"sex" : 1,
			"job" : "前端",
			"skill" : {
					"skillOne" : "HTML+CSS",
					"SkillTwo" : "JavaScript",
					"SkillThree" : "PHP"
			},
			"regeditTime" : ISODate("2019-07-30T08:06:34.505Z"),
			"money" : 1000
	},
	"ok" : 1
}


# findAndModify属性值

query:需要查询的条件/文档
sort: 进行排序
remove:[boolean]是否删除查找到的文档,值填写true,可以删除。
new:[boolean]返回更新前的文档还是更新后的文档。
fields:需要返回的字段
upsert:没有这个值是否增加。

# js文件写mongodb

var userName="jspang";          

var jsonDdatabase={"loginUnser":userName}
var db = connect("apple");  
db.login.insert(jsonDdatabase); 
 
print("[demo]log  print success"); 
 //mongo xx.js

# find不等修饰符

  1. 筛选字段
db.workmate.find(
    {"skill.skillOne":"HTML+CSS"},
    {name:true,"skill.skillOne":true}
)
//默认会显示_id的,如果不需要,可以设为false
  1. 修饰符
  • 小于($lt):英文全称less-than
  • 小于等于($lte):英文全称less-than-equal
  • 大于($gt):英文全称greater-than
  • 大于等于($gte):英文全称greater-than-equal
  • 不等于($ne):英文全称not-equal
//公司内年龄小于30大于25岁的人员。看下面的代码。
db.workmate.find(
    {age:{$lte:30,$gte:25}},
    {name:true,age:true,"skill.skillOne":true,_id:false}
)

# find多条件查询

//$in相对的修饰符是$nin
db.workmate.find({age:{$in:[25,33]}},
    {name:1,"skill.skillOne":1,age:1,_id:0}
)
//查询同事中大于30岁或者会做PHP的信息
db.workmate.find({$or:[
    {age:{$gte:30}},
    {"skill.skillThree":'PHP'}
]},
    {name:1,"skill.skillThree":1,age:1,_id:0}
)
//查询同事中大于30岁并且会做PHP的信息
db.workmate.find({$and:[
    {age:{$gte:30}},
    {"skill.skillThree":'PHP'}
]},
    {name:1,"skill.skillThree":1,age:1,_id:0}
)
//注意$not修饰符不能应用在条件语句中,只能在外边进行查询使用。
db.workmate.find({
    age:{
        $not:{
            $lte:30,
            $gte:20
        }
    }
},
{name:1,"skill.skillOne":1,age:1,_id:0}
)

# find基本数组查询

//加上中括号就相当于完全匹配了
db.workmate.find({interest:['画画','聚会','看电影']},
    {name:1,interest:1,age:1,_id:0} 
)V
//如果只想查数组里可能的一个值,不需要加中括号
db.workmate.find({$and:[{interest:'看电影'},{interest:'聚会'}]},
    {name:1,interest:1,age:1,_id:0} 
)

# $all

查询出喜欢看电影和看书的人员信息,也就是对数组中的对象进行查询,这时候要用到一个新的查询修饰符$all

db.workmate.find(
    {interest:{$all:["看电影","看书"]}},
    {name:1,interest:1,age:1,_id:0} 
)

# $in

$in主要满足数组中的一项就可以被查出来

db.workmate.find(
    {interest:{$in:["看电影","看书"]}},
    {name:1,interest:1,age:1,_id:0} 
)

# $size

$size修饰符可以根据数组的数量查询出结果。要查找兴趣的数量是5个人员信息,这时候就可以使用$size。

db.workmate.find(
    {interest:{$size:5}},
    {name:1,interest:1,age:1,_id:0} 
)

# $slice-显示选项

//显示每个人兴趣的前两项,而不是把每个人所有的兴趣都显示出来。
db.workmate.find(
    {},
    {name:1,interest:{$slice:2},age:1,_id:0} 
)
//显示兴趣的最后一项,可以直接使用slice:-1
db.workmate.find(
    {},
    {name:1,interest:{$slice:-1},age:1,_id:0} 
)

# find参数

  • query:这个就是查询条件,MongoDB默认的第一个参数。
  • fields:(返回内容)查询出来后显示的结果样式,可以用true和false控制是否显示。
  • limit:返回的数量,后边跟数字,控制每次查询返回的结果数量。
  • skip:跳过多少个显示,和limit结合可以实现分页。
  • sort:排序方式,从小到大排序使用1,从大到小排序使用-1
db.workmate.find({},{name:true,age:true,_id:false}).limit(0).skip(2).sort({age:1});

# $where

//this指向的是workmate(查询集合)本身。这样可以在程序中随意调用。
//虽然强大灵活,但这种查询对于数据库的压力和安全性都会变重,所以尽量减少$where修饰符的使用。
db.workmate.find(
    {$where:"this.age>30"},
    {name:true,age:true,_id:false}
)

# 循环打印数据

var db = connect("company")  //进行链接对应的集合collections
var result = db.workmate.find() //声明变量result,并把查询结果赋值给result
//利用游标的hasNext()进行循环输出结果。
while(result.hasNext()){
    printjson(result.next())  //用json格式打印结果
}
---------------
var db = connect("company")  //进行链接对应的集合collections
var result = db.workmate.find() //声明变量result,并把查询结果赋值给result
result.forEach(function(result){
    printjson(result)
})

# 导入百万数据

//生成随机数
 
function GetRandomNum(min,max){
    let range = max-min;   //得到随机数区间
    let rand = Math.random(); //得到随机值
    return (min + Math.round(rand *range)); //最小值+随机数取整
}
 
//console.log(GetRandomNum(10000,99999));
 
//生成随机用户名
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;
}
 
// console.log(GetRadomUserName(7,16))
// var startTime=(new Date()).getTime();
// 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),
        randNum8:GetRandomNum(100000,999999),
    })
}
 
db.randomInfo.insert(tempInfo);

# 普通查询

var startTime = new Date().getTime()  //得到程序运行的开始时间

var rs=db.randomInfo.find({username:"tfruhjy8k"})  
var  runTime = new Date().getTime()-startTime;      //得到程序运行时间
print('[SUCCESS]This run time is:'+runTime+'ms')    //打印出运行时间

# 建立索引

无论是在关系型数据库还是文档数据库,建立索引都是非常重要的。索引这东西是要消耗硬盘和内存资源的,所以还是要根据程序需要进行建立了。MongoDB也进行了限制,只允许我们建立64个索引值。

试着为用户名(username)建立索引。建立索引只需要一句话就可以了。

db.randomInfo.ensureIndex({username:1})

查看现有索引

db.randomInfo.getIndexes()

总结

  • 数据不超万条时,不需要使用索引。性能的提升并不明显,而大大增加了内存和硬盘的消耗。
  • 查询数据超过表数据量30%时,不要使用索引字段查询。实际证明会比不使用索引更慢,因为它大量检索了索引表和我们原表。
  • 数字索引,要比字符串索引快的多,在百万级甚至千万级数据量面前,使用数字索引是个明确的选择。
  • 把你经常查询的数据做成一个内嵌数据(对象型的数据),然后集体进行索引。

# 复合索引

复合索引就是两条以上的索引

db.randomInfo.find({username:'7xwb8y3',randNum0:565509});
# 指定索引查询(hint)

数字的索引要比字符串的索引快,这就需要一个方法来打破索引表的查询顺序,用指定的索引优先查询,这个方法就是hint().

db.randomInfo.find({username:'7xwb8y3',randNum0:565509}).hint({randNum0:1});
# 删除索引

当索引性能不佳或起不到作用时,我们需要删除索引,删除索引的命令是dropIndex().

//新建
db.randomInfo.ensureIndex({randNum0:1})
//查看
db.randomInfo.getIndexes()
//删除
db.randomInfo.dropIndex('randNum0_1');//索引的唯一ID
 {
	"v" : 2,
	"key" : {
		"randNum0" : 1
	},
	"name" : "randNum0_1",
	"ns" : "company.randomInfo"
}

注意

这里需要注意的是删除时填写的值,并不是我们的字段名称(key),而是我们索引查询表中的name值。

# 建立全文索引
db.info.ensureIndex({contextInfo:'text'})

需要注意的是这里使用text关键词来代表全文索引。

建立好了全文索引就可以查找了,查找时需要两个关键修饰符:

  • $text:表示要在全文索引中查东西。
  • $search:后边跟查找的内容。 db.info.find({$text:{$search:"programmer"}})

查找多个词

全文索引是支持多个次查找的,比如我们希望查找数据中有programmer,family,diary,drink的数据(这是或的关系),所以两条数据都会出现。

db.info.find({$text:{$search:"programmer family diary drink"}})

如果希望不查找出来有drink这个单词的记录,我们可以使用“-”减号来取消。

dbd .info.find({$text:{$search:"programmer family diary -drink"}})

转义符:

全文搜索中是支持转义符的,比如我们想搜索的是两个词(love PlayGame和drink),这时候需要使用\斜杠来转意。

db.info.find({$text:{$search:"\"love PlayGame\" drink"}})

# 数据备份

mongodump备份的基本格式

mongodump
    --host 127.0.0.1
    --port 27017
    --out D:/databack/backup
    --collection myCollections
    --db test
    --username username
    --password password
//比如现在我们备份所有MongoDB里的库到D盘的databack文件夹下,就可以把命令写成这样

mongodump --host 127.0.0.1 --port 27017 --out D:/databack/

# 数据恢复

mongorestore
    --host 127.0.0.1
    --port 27017
    --username username
    --password password
    <path to the backup>
mongorestore --host 127.0.0.1 --port 27017 D:/databack/

# node操作mongodb

需要引包

npm install mongodb
var express = require("express");
//数据库引用
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');

var app = express();

//数据库连接的地址,最后的斜杠表示数据库名字
var shujukuURL = 'mongodb://localhost:27017/itcast';

app.get("/",function(req,res){
	res.writeHead(200,{"Content-type":"text/html;charset=UTF-8"});
    //连接数据库,这是一个异步的操作
    MongoClient.connect(shujukuURL, function(err, db) {
        if(err){
            res.send("数据库连接失败");
            return;
        }
        res.write("恭喜,数据库已经成功连接 \n");
        db.collection("teacher").insertOne({"name":"哈哈"},function(err,result){
            if(err){
                res.send("数据库写入失败");
                return;
            }
            res.write("恭喜,数据已经成功插入");
            res.end();
            //关闭数据库
            db.close();
        });
    });
});

app.listen(3000);
最后更新: 7/31/2019, 1:43:49 PM