在冰岩实习期间用一天多的时间把超哥的mongoDB视频刷了一遍,并且有了一些实践,但是一个月后还是忘得差不多了,现在打算再刷一次:尚硅谷MongoDB基础教程(数据库精讲)
在MongoDB中,数据库和集合都不需要手动创建,当创建文档时,如果文档所在的集合或数据库不存在,会自动创建数据库和集合。数据库会在第一次向其中插入文档的时候创建
- MongoDB的基本的指令
- 启动服务器
mongod --dbpath 路径 --port 端口号
- 启动客户端
mongo
- MongoDB的CRUD的操作
- 基本操作
use 数据库
- 进入指定的数据库
show dbs
- 显示所有的数据库
show collections
- 显示数据库中所有的集合
db
- 显示当前所在的数据库
- 向数据库中插入文档
- db.collection.insert()
- insert()可以向集合中插入一个或多个文档
- db.collection.insertOne()
- 向集合中插入一个文档
- db.collection.insertMany()
- 向集合中插入多个文档
- 查询数据库中的文档
- db.collection.find()
- 可以根据指定条件从集合中查询所有符合条件的文档
- 返回的是一个数组
- db.collection.findOne()
- 查询第一个符合条件的文档
- 返回的是一个对象
- db.collection.find().count()
- 查询符合条件的文档的数量
- 修改数据库中的文档
- db.collection.update()
- 可以修改、替换集合中的一个或多个文档
- db.collection.updateOne()
- 修改集合中的一个文档
- db.collection.updateMany()
- 修改集合中的多个文档
- db.collection.replaceOne()
- 替换集合中的一个文档
- 删除集合中的文档
- db.collection.remove()
- 删除集合中的一个或多个文档(默认删除多个)
- db.collection.deleteOne()
- 删除集合中的一个文档
- db.collection.deleteMany()
- 删除集合中的多个文档
- 清空一个集合
db.collection.remove({})
- 删除一个集合
db.collection.drop()
- 删除一个数据库
db.dropDatabase()
//1.进入my_test 数据库
use my_test
//2.向数据据库的user集合中插入一个文档
db.users.insert({
username:"sunwukong"
});
//3.查询user集合中的文档
db.users.find();
//4.统计数据库user集合中的文档数量
db.users.find().count();
//5.查询数据库user集合中username为sunwukong的文档
db.users.find({username:"sunwukong"});
//注意,写成这样不代表username值一定为sunwukong,也可以值为一个数组,数组内含有sunwukong这个元素
//6.向数据库user集合中的username为sunwukong的文档,添加一个address属性
//$set是操作符(operator),或称修改器
db.users.update({username:"sunwukong"},{$set:{address:"huaguoshan"}});
//7.使用{username:"tangseng"}替换username为zhubajie的文档
db.users.replaceOne({username:"zhubajie"},{username:"tangseng"});
db.users.updateOne({username:"sunwukong"},{username:"tangseng"});
//8.删除username为sunwukong的文档的address属性
db.users.update({username:"sunwukong"},{$unset:{address:1}});
//由于只是想删除属性,和值没有关系,所以值可以随便写
//9.向username为sunwukong的文档中,添加一个hobby:{cities:["beijing","shanghai","shenzhen"]}
db.users.update({username:"sunwukong"},{
&set:{hobby:{cities:["beijing","shanghai","shenzhen"]}});
//当一个文档的属性值也是一个文档时,称这个文档为内嵌文档
//10.查询喜欢电影hero的文档
//查询内嵌文档通过.的形式来匹配,属性名必须使用引号
db.users.find({
"hobby.movies":"hero"});
//11.向tangseng中添加一个新的电影Interstellar
//$push 用于向数组中添加一个新的元素
//$addToSet 和$push类似,但如果数组中已经存在该元素,则不会添加
db.users.update({username:"tangseng"},{$push:{
"hobby.movies":"Interstellar"}});
db.users.update({username:"tangseng"},{$addToSet:{
"hobby.movies":"Interstellar"}});
//12.删除喜欢beijing的用户
db.users.remove({
"hobby.cities":"beijing"});
//13.删除user集合
//通过删除全部文档实现
db.users.remove({});
//直接删除集合
db.users.drop();
//14.插入1到20000
let arr = [];
for(let i = 1; i <= 20000; i++) {
arr.push({num:i});
}
db.numbers.insert(arr);
//如果直接循环向数据库插入数据,效率会很低
//因此推荐其他操作在插入之前完成,尽量少调用数据库的方法,因为性能不好
//15.查看numbers集合中的前10条数据
//limit()设置显示数据的上限
db.numbers.find().limit(10);
//16.查看numbers集合中的第11条到20条数据
//skip()和limit()的顺序没有影响,mongoDB会自动调整为skip()在前
db.numbers.find().skip(10).limit(10);
一对一:通过内联文档来映射一对多的关系
一对多:同上,用id
多对多:同上,把id放在数组内
一对一:
db.wifeAndHusband.insert([
{
name: "黄蓉",
husband: {name:"郭靖"}
},
{
name: "潘金莲",
husband: {name: "武大郎"}
}
]);
一对多:(在订单中保存用户的id)
db.users.insert([
{username:"swk"},
{username:"zbj"}
]);
db.order.insert({
list: ["苹果", "香蕉", "大鸭梨"],
user_id: ObjectId("59c47e35241d8d36a1d50ddf") //这是swk的订单
})
db.order.insert({
list: ["西瓜", "香蕉"],
user_id: ObjectId("59c47e35241d8d36a1d50ddf") //这是swk的订单
})
db.order.insert({
list: ["牛肉", "漫画"],
user_id: ObjectId("59c47e35241d8d36a1d50de0") //这是zbj的订单
})
//查询swk的订单
var user_id = db.users.findOne({username: "zbj"})._id;
db.order.find({user_id: user_id}); //前面是属性名,后面是属性值
多对多:
db.teachers.insert([
{name: "洪七公"},
{name: "黄药师"},
{name: "龟仙人"}
]);
db.stus.insert([
{
name: "郭靖",
tech_ids:[
ObjectId("59c4806d241d8d36a1d50de4"), //对应洪七公
ObjectId("59c4806d241d8d36a1d50de5") //对应黄药师
]
},
{
name: "小悟空",
tech_ids:[
ObjectId("59c4806d241d8d36a1d50de4"), //对应洪七公
ObjectId("59c4806d241d8d36a1d50de5") //对应黄药师
ObjectId("59c4806d241d8d36a1d50de6") //对应龟仙人
]
}
])
此处部门在dept集合内,员工在emp集合内(P14)
//1.查询工资小于1000或大于2500的员工
db.emp.find({$or:[{sal: {$lt: 1000}}, {sal: {$gt: 2500}}]});
//2.查询销售部的所有员工
//注意find返回的是一个数组,如果用find,要加下标
let depno = db.dept.findOne({dname: "销售部"}).depno;
db.emp.find({depno: depno});
//3.为所有薪资不超过1000的员工增加400元
//$inc 是自增操作符
db.emp.updateMany({sal:{$lte: 1000}}, {$inc: {sal: 400}});
//查询文档时,默认情况是按照_id的值进行升序排列
//sort()可以用来指定文档的排序规则,sort()需要传递一个对象来指定排序规则
//1表示升序,-1表示降序
db.emp.find({}).sort({sal: 1, empno: -1}); //按工资升序,按部门编号降序
//在查询时,可以在第二个参数的位置来设置查询结果的投影
//默认情况下都会查询_id,只有_id: 0 时才不会查询
db.emp.find({}, {ename: 1, _id: 0, sal: 1});
mongoose提供的新的对象:
1.下载安装Mongoose
npm i mongoose --save
2.在项目中引入mongoose
let mongoose = require("mongoose");
3.连接MongoDB数据库
mongoose.connect('mongodb://数据库的ip地址:端口号/数据库名', { useMongoClient: true});
- 如果端口号是默认端口号(27017) 则可以省略不写
4.断开数据库连接(一般不需要调用)
- MongoDB数据库,一般情况下,只需要连接一次,连接一次以后,除非项目停止服务器关闭,否则连接一般不会断开
mongoose.disconnect()
- 监听MongoDB数据库的连接状态
- 在mongoose对象中,有一个属性叫做connection,该对象表示的就是数据库连接
通过监视该对象的状态,可以来监听数据库的连接与断开
数据库连接成功的事件
mongoose.connection.once("open",function(){});
数据库断开的事件
mongoose.connection.once("close",function(){});
Schema
Model
Document
操作:
//引入
let mongoose = require("mongoose");
//连接数据库
mongoose.connect("mongodb://127.0.0.1/mongoose_test");
mongoose.connection.once("open",function(){
console.log("数据库连接成功");
});
mongoose.connection.once("close",function(){
console.log("数据库连接已经断开");
});
//断开数据库连接(一般不会主动断开)
mongoose.disconnect();
//将mongoose.Schema 赋值给一个变量
let Schema = mongoose.Schema;
//创建Schema(模式)对象
var stuSchema = new Schema({
name:String,
age:Number,
gender:{
type:String,
default:"female"
},
address:String
});
//通过Schema来创建Model
//Model代表的是数据库中的集合,通过Model才能对数据库进行操作
//mongoose.model(modelName, schema):
//modelName 就是要映射的集合名 mongoose会自动将集合名变成复数
var StuModel = mongoose.model("student" , stuSchema);
//向数据库中插入一个文档
//StuModel.create(doc, function(err){});
StuModel.create({
name:"白骨精",
age:16,
address:"白骨洞"
},function (err) {
if(!err){
console.log("插入成功~~~");
}
});
有了Model,就可以对数据库进行增删改查的操作了
Model.create(doc(s), [callback])
- 用来创建一个或多个文档并添加到数据库中
- 参数:
doc(s) 可以是一个文档对象,也可以是一个文档对象的数组
callback 当操作完成以后调用的回调函数
StuModel.create([
{
name: "猪八戒",
age: 28,
gender: "male",
address: "高老庄"
},
{
name: "唐僧",
age: 16,
gender: "male",
address: "女儿国"
}
],function (err) {
if(!err) {
console.log("插入成功");
}
})
注意find返回的是数组,findOne和findById返回的是一个文档对象Document
Document对象是Model的实例,可以用instanceOf验证
查询:
Model.find(conditions, [projection], [options], [callback])
- 查询所有符合条件的文档 总会返回一个数组
Model.findById(id, [projection], [options], [callback])
- 根据文档的id属性查询文档
Model.findOne([conditions], [projection], [options], [callback])
- 查询符合条件的第一个文档 总和返回一个具体的文档对象
conditions 查询的条件
projection 投影 需要获取到的字段
- 两种方式
{name:1,_id:0}
"name -_id"
options 查询选项(skip limit)
{skip:3 , limit:1}
callback 回调函数,查询结果会通过回调函数返回
回调函数必须传,如果不传回调函数,则不会查询
StuModel.find({
name:"唐僧"},function (err , docs) {
//当使用find,返回的是数组时,习惯写成docs
if(!err){
console.log(docs);
}
});
StuModel.find({
},"name age -_id", {
skip:3 , limit:1} , function (err , docs) {
if(!err){
console.log(docs);
}
});
StuModel.findOne({
} , function (err , doc) {
//当使用findOne或findById,返回的是一个文档对象时,习惯写成doc
if(!err){
console.log(doc);
}
});
StuModel.findById("59c4c3cf4e5483191467d392" , function (err , doc) {
if(!err){
console.log(doc instanceof StuModel); //true
}
});
修改:
Model.update(conditions, doc, [options], [callback])
Model.updateMany(conditions, doc, [options], [callback])
Model.updateOne(conditions, doc, [options], [callback])
- 用来修改一个或多个文档
- 参数:
conditions 查询条件
doc 修改后的对象
options 配置参数
callback 回调函数
Model.replaceOne(conditions, doc, [options], [callback])
//修改唐僧的年龄为20
StuModel.updateOne({
name:"唐僧"},{
$set:{
age:20}},function (err) {
if(!err){
console.log("修改成功");
}
});
一般情况下,不会调用删除API
/*
删除:
Model.remove(conditions, [callback])
Model.deleteOne(conditions, [callback])
Model.deleteMany(conditions, [callback])
*/
StuModel.remove({
name:"白骨精"},function (err) {
if(!err){
console.log("删除成功");
}
});
/*
Model.count(conditions, [callback])
- 统计文档的数量
*/
StuModel.count({
},function (err , count) {
if(!err){
console.log(count);
}
});
let stu = new StuModel({
name:"奔波霸",
age:48,
gender:"male",
address:"碧波潭"
});
stu.save(function (err) {
if(!err){
console.log("保存成功~~~");
}
});
StuModel.findOne({
},function (err , doc) {
if(!err){
//console.log(doc);
doc.update({
$set:{
age:28}},function (err) {
if(!err){
console.log("修改成功");
}
});
//以上代码等价于:
doc.age = 18;
doc.save();
doc.remove(function (err) {
if(!err){
console.log("删除成功");
}
});
get和set感觉没什么用
将Document对象转化为普通的JS对象,当有属性想要删除时,先转为普通对象。
转为普通对象后,不能调用Document的方法,且获取id时不能.id,必须._id(Document对象可以.id)
let o = doc.toObject();
doc = doc.toObject();
delete doc.address; //先转为普通对象,然后才删得掉
console.log(doc._id); //如果写成doc.id,则得到undefined
文件结构:
- tools
- conn_mongo.js
- models
- student.js
index.js
conn_mongo.js:封装连接到mongoDB数据库的代码
let mongoose = require("mongoose");
mongoose.connect("mongodb://127.0.0.1/mongoose_test");
mongoose.connection.once("open",function () {
console.log("数据库连接成功");
})
student.js: 用来定义Student的模型
let mongoose = require("mongoose");
let Schema = mongoose.Schema;
let stuSchema = new Schema({
name: String,
age: Number,
gender:{
type:String,
default: "female"
},
address:String
});
let StuModel = mongoose.model("student", stuSchema);
module.exports = StuModel; //导出单个成员,省去在index.js里用点的麻烦
index.js:顾名思义
require("./tools/conn_mongo");
let Student = require("./models/student");
Student.find({
}, function (err, docs) {
if(!err) {
console.log(docs);
}
});