Danmo的学习之路(mongoDB & mongoose)

在冰岩实习期间用一天多的时间把超哥的mongoDB视频刷了一遍,并且有了一些实践,但是一个月后还是忘得差不多了,现在打算再刷一次:尚硅谷MongoDB基础教程(数据库精讲)

mongoDB

在MongoDB中,数据库和集合都不需要手动创建,当创建文档时,如果文档所在的集合或数据库不存在,会自动创建数据库和集合。数据库会在第一次向其中插入文档的时候创建

常用指令与CRUD

- 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}});

sort和投影

//查询文档时,默认情况是按照_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

简介

mongoose提供的新的对象:

  • Schema(模式对象/约束):定义约束了数据库中的文档结构
  • Model:相当于MongoDB数据库中的集合collection
  • Document:相当于集合中的一个具体的文档
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();

Schema和Model

//将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)

 	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)

注意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
	}
});

改(update)

 修改:
 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("修改成功");
	}
});

删(delete/remove)

一般情况下,不会调用删除API

/*
 删除:
 Model.remove(conditions, [callback])
 Model.deleteOne(conditions, [callback])
 Model.deleteMany(conditions, [callback])
*/

StuModel.remove({name:"白骨精"},function (err) {
	if(!err){
		console.log("删除成功");
	}
});

文档个数(count)

/*
 Model.count(conditions, [callback])
 	- 统计文档的数量
 */
StuModel.count({},function (err , count) {
	if(!err){
		console.log(count);
	}
});

Document的方法

save

let stu = new StuModel({
	name:"奔波霸",
	age:48,
	gender:"male",
	address:"碧波潭"
});

stu.save(function (err) {
	if(!err){
		console.log("保存成功~~~");
	}
});

update && remove

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感觉没什么用

toObject

将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

mongoose 模块化

文件结构:

- 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);
	}
});
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值