第一種
安裝
在命令行中下載mongoose
npm install mongoose --save
引入mongoose并連接數據庫
// 引入第三方包mongoose
const mongoose = require('mongoose');
// 要管理員的賬號和密碼才能進行數據庫操作
// mongoose.connect('mongodb://user:pass@localhost:port/database')
// user表示用戶名,pass表hi是密碼,port表示數據庫的端口mongodb的默認端口27017,database表示數據庫的名字
// 連接數據庫
mongoose.connect('mongodb://127.0.0.1/blog', {
useUnifiedTopology: true,
useNewUrlParser: true
}).then(() => { //這里面的then()方法是如果成功輸出成功,如果失敗在catch()方法里面輸出失敗
console.log('數據庫成功');
}).catch(() => {
console.log('失敗');
});
配置Schema(通過require獲取)
就是
// 1.引入mongoose模塊
const mongoose = require('mongoose');
// 2.創(chuàng)建文章集合類型 定義一個Schema Schema里面的對象和數據庫表里面的字段需要一一對應
const articleSchema = new mongoose.Schema({
title: {
type: String,
maxlength: 20, //最大長度
minlength: 4, //最小長度
required: [true, '請?zhí)顚懳恼聵祟}'] //第一個參數是告訴這個是必填字段匈辱,第二個參數表示錯誤信息
},
author: {
type: mongoose.Schema.Types.ObjectId, //要將文章中的作者和用戶中的作者進行關聯
ref: 'User', //這個屬性就是用來將文章集合和用戶集合進行關聯’User‘就是集合的名字
required: [true, '請傳遞作者'],
},
publishDate: {
type: Date,
default: Date.now,
},
cover: {
type: Number,
default: 1 //表示默認參數涡上,如果不寫,那么數據庫就會默認為1
},
content: {
type: String
}
});
// 3.根據規(guī)則常見集合,定義數據庫模型 操作數據庫
// model 里面的第一個參數要注意首字母要大寫 2,要和數據庫表(集合名稱對應)
// 第二個參數要和Schema上面的一樣
const Article = mongoose.model('Article', articleSchema);
//Article會默認和數據庫中的Articles進行連接,我們也可以指定數據名詞高镐,設置第三個參數就OK了
//這樣那么Article就和artes建立了連接
//const Article = mongoose.model('Article', articleSchema,'artes');
// 4.將集合規(guī)則作為模板成員進行導出
module.exports = {
Article
}
模塊化配置
就是通過導入導出的方式來進行模塊化
const mongoose = require('mongoose');
mongoose.connect('mongodb://127.0.0.1/blog', {
useUnifiedTopology: true,
useNewUrlParser: true
}).then(() => { //這里面的then()方法是如果成功輸出成功,如果失敗在catch()方法里面輸出失敗
console.log('數據庫成功');
}).catch(() => {
console.log('失敗');
});
// 導出數據
module.exports=mongoose;
引入數據庫
// 1.引入mongoose模塊
const mongoose = require('mongoose');
// 2.創(chuàng)建文章集合類型
const articleSchema = new mongoose.Schema({
title: {
type: String,
maxlength: 20, //最大長度
minlength: 4, //最小長度
required: [true, '請?zhí)顚懳恼聵祟}'] //第一個參數是告訴這個是必填字段一汽,第二個參數表示錯誤信息
},
author: {
type: mongoose.Schema.Types.ObjectId, //要將文章中的作者和用戶中的作者進行關聯
ref: 'User', //這個屬性就是用來將文章集合和用戶集合進行關聯’User‘就是集合的名字
required: [true, '請傳遞作者'],
},
publishDate: {
type: Date,
default: Date.now,
},
cover: {
type: String,
default: null
},
content: {
type: String
}
});
// 3.根據規(guī)則常見集合
const Article = mongoose.model('Article', articleSchema);
// 4.將集合規(guī)則作為模板成員進行導出
module.exports = {
Article
}
操作那個數據庫引入就可以了
require('./')
操作添加避消,刪除,修改
預定義修飾符
lowercase召夹、uppercase岩喷、trim
mongoose提供了預定義模式修飾符,可以對我們的數據進行一些格式化
// 1.引入mongoose模塊
const mongoose = require('mongoose');
// 2.創(chuàng)建文章集合類型
const articleSchema = new mongoose.Schema({
title: {
type: String,
maxlength: 20, //最大長度
minlength: 4, //最小長度
required: [true, '請?zhí)顚懳恼聵祟}'], //第一個參數是告訴這個是必填字段监憎,第二個參數表示錯誤信息
trim:true //表示的是如果用戶輸入的數據兩邊有空格可以通過這個方法取消空格
}
});
自定義修飾符Getters與Setters
除了mongoose內置的修飾符以外纱意,我們還可以通過set(建議使用)修飾符在增加數據的時候對數據進行格式化
也可以通過get(不建議使用)在實力獲取數據
的時候對數據進行格式化。
這是set方法
// 1.引入mongoose模塊
const mongoose = require('mongoose');
// 2.創(chuàng)建文章集合類型
const articleSchema = new mongoose.Schema({
title: {
type: String,
maxlength: 20, //最大長度
minlength: 4, //最小長度
required: [true, '請?zhí)顚懳恼聵祟}'], //第一個參數是告訴這個是必填字段鲸阔,第二個參數表示錯誤信息
trim:true //表示的是如果用戶輸入的數據兩邊有空格可以通過這個方法取消空格
pic:{
type:String,
set(parmas){ //增加數據的時候對pic字段進行處理
//parmas可以獲取pic的值偷霉、返回的數據就是pic在數據庫中實際保存的值
/**
*www.baidu.com http://www.baidu.com
*http://www.baidu.com http://www.baidu.com
*/
//如果用戶沒有傳入地址
if(!parmas){
return '';
}else{
if(parmas.indexOf('http://')!=0 $$ parmas.indexOf('http://')!=0){
return 'http://'+parmas;
}
return parmas;
}
}
} //表示自定義例如我們必須要http://www.baidu.com,但是有些用戶不輸入http://,所以需要進行自定義設置
}
});
這是get方法可以去看一下褐筛,不好用
// 1.引入mongoose模塊
const mongoose = require('mongoose');
// 2.創(chuàng)建文章集合類型
const articleSchema = new mongoose.Schema({
title: {
type: String,
maxlength: 20, //最大長度
minlength: 4, //最小長度
required: [true, '請?zhí)顚懳恼聵祟}'], //第一個參數是告訴這個是必填字段类少,第二個參數表示錯誤信息
trim:true //表示的是如果用戶輸入的數據兩邊有空格可以通過這個方法取消空格
name:{
type:String,
get(params){
return "a001"+params //表示的是在獲取數據的時候添加一個a001(只有同過什么.什么添加的時候)
}
}
}
});
Mongoose的索引
索引是對數據庫表中一列或多列的值進行排序的一種結構,可以讓我們查詢數據庫變得更快渔扎,MONGODB的索引幾乎與傳統(tǒng)的關系型數據庫一模一樣硫狞,這其中也包括了一些基礎的查詢優(yōu)化技巧。
mongoose中除了以前創(chuàng)建索引的方式晃痴,我們也可以在定義Schema的時候指定創(chuàng)建索引残吩。
// 2.創(chuàng)建文章集合類型 定義一個Schema Schema里面的對象和數據庫表里面的字段需要一一對應
const articleSchema = new mongoose.Schema({
title: {
type: String,
// 唯一索引、
unique:true
},
cover: {
type: String,
/// 普通索引
index:true,
default: null
},
publishDate: {
type: Date,
default: Date.now,
},
content: {
type: String
}
});
mongoose內置的CURD方法
[圖片上傳失敗...(image-4b0014-1601889185797)]
就是有的搜索時finByID我們也可以根據屬性來自定義一個
const articleSchema = new mongoose.Schema({
title: {
type: String,
maxlength: 20, //最大長度
minlength: 4, //最小長度
required: [true, '請?zhí)顚懳恼聵祟}'] //第一個參數是告訴這個是必填字段倘核,第二個參數表示錯誤信息
},
sn:{
},
content: {
type: String
}
});
//靜態(tài)方法(要加一個statics)
articleSchema.statics.findBySn=function(sn,cb){
this.find({"sn":sn},function(err,docs){
cd(err,docs);
})
}
//實例方法(基本沒用)
articleSchema.methods.print=function(sn,cb){
console.log(this)
}
// 然后存儲一個信息
var user=new articleSchema({
title:'2312',
sn:'123456',
content:'29'
});
user.save();
//靜態(tài)方法
// 通過Model.findBySn('123456',(){})來查詢數據
// 實例方法
//user.print();
數據校驗
這是在Schema里面
required:表示這個數據必須傳入
max:用于Number類型數據泣侮,最大值
min:用于Number類型數據,最小值
enum:枚舉類型紧唱,要求數據必須滿足枚舉值 enum:['0','1','2']注意它使用在String類型中的
match:增加的數據必須符合match(正則)的規(guī)則 注意它使用在String類型中的
maxlenth:最大長度
minlength:最小長度
default:表示默認值
自定義數據校驗
const articleSchema = new mongoose.Schema({
title: {
type: String,
maxlength: 20, //最大長度
minlength: 4, //最小長度
required: [true, '請?zhí)顚懳恼聵祟}'] //第一個參數是告訴這個是必填字段活尊,第二個參數表示錯誤信息
},
content: {
type: String,
//自定義數據校驗 任意的類型里面
validate:function(sn){
return sn.length>=10;
}
}
});
**mongoose中使用aggregate聚合管道(后期可以在看一下)
都可以寫多次
$project(篩選指定的列)
修改文檔結構,可以用來重命名漏益,增加或刪除文檔中的字段酬凳。
要求查找order只返回文檔中的teade_no和all_price字段(order表示數據表)
order.aggregate([ //每一個管道是一個對象,對象里面實現具體的功能
{
$project:{teade_no:1,all_price1}
}
])
$match(過濾)
作用:用于過濾文檔遭庶,用法類似于find()方法中的參數宁仔。
order.aggregate([ //每一個管道是一個對象,對象里面實現具體的功能
{
$project:{teade_no:1,all_price1}
},
{
$match:{"all_price":{$gte:90}} //這個意思時查找總價格大于90的數據
}
])
$group???沒懂
將集合中的文檔進行分組峦睡,可用于統(tǒng)計結果
統(tǒng)計每個訂單的訂單數量翎苫,按照訂單號分組
order.aggregate([ //每一個管道是一個對象,對象里面實現具體的功能
{
$group:{_id:"$order_id",total:{$sum:1}}
}
])
$sort(排序)
將集合文檔進行排序
order.aggregate([ //每一個管道是一個對象榨了,對象里面實現具體的功能
{
$project:{teade_no:1,all_price1}
},
{
$match:{"all_price":{$gte:90}} //這個意思時查找總價格大于90的數據
},
{
$sort:{"all_price":-1} //以 all_price進行排序 -1降序 1升序
}
])
$limit(查幾條數據)
order.aggregate([ //每一個管道是一個對象煎谍,對象里面實現具體的功能
{
$project:{teade_no:1,all_price1}
},
{
$match:{"all_price":{$gte:90}} //這個意思時查找總價格大于90的數據
},
{
$sort:{"all_price":-1} //以 all_price進行排序 -1降序 1升序
},
{
$limit:1 //表示只返回一條數據
}
])
$skip (跳過幾條數據)
order.aggregate([ //每一個管道是一個對象,對象里面實現具體的功能
{
$project:{teade_no:1,all_price1}
},
{
$match:{"all_price":{$gte:90}} //這個意思時查找總價格大于90的數據
},
{
$sort:{"all_price":-1} //以 all_price進行排序 -1降序 1升序
},
{
$skip:1 //跳過幾條數據
}
])
$unwind
$unwind管道以document中的數組類型的字段進行拆分龙屉,每條包含數組中的一個值呐粘。
比如拆分likes:10
這條數據满俗,先來看看整體數據信息吧:
{
"_id" : ObjectId("5e86e2ad88e64443e448dfd2"),
"title" : "NoSQL Overview",
"description" : "No sql database is very fast",
"by_user" : "runoob.com",
"url" : "http://www.runoob.com",
"tags" : [
"mongodb",
"database",
"NoSQL"
],
"likes" : 10
}
router.get('/getInfo', async (req, res) => {
let data = await Content.aggregate([
{
$match: {
likes: 10
}
},
{
$unwind:'$tags'
},
{
$project: { _id: 1, by_user: 1, title: 1, title: 1, description: 1, url: 1, tags: 1, likes: 1 }
},
])
res.json({
data
})
})
$lookup(表關聯操作)
order.aggregate([ //每一個管道是一個對象,對象里面實現具體的功能
{
$lookup:{
from:"order_item", //就是你這個表要和那個表進行關聯
localField:"order_id", //表示你order表關聯的字段
foreignField:"order_id", //表示你order_item表與order表關聯的id
as:"items" //as表示你要關聯的數據要放在哪里order的那個屬性里面
}
}
])
//想獲取的這樣的數據
[
{
Order_id:"",
Trade_no:"",
items:[
{
title:"鼠標",
name:"名字"
},
{
title:"鍵盤",
name:"名字"
}
]
}
]
//要觀察誰關聯誰
db.order.insert([
{ order_id: "1", uid: 10, trade_no: "111", all_price: 100, all_num: 2 },
{ order_id: "2", uid: 7, trade_no: "222", all_price: 90, all_num: 2 },
{ order_id: "3", uid: 9, trade_no: "333", all_price: 20, all_num: 6 }
]);
//=================================
db.order_item.insert([
{ order_id: "1", title: "商品鼠標1", price: 50, num: 1 },
{ order_id: "1", title: "商品鼠標2", price: 50, num: 1 },
{ order_id: "1", title: "商品鼠標3", price: 0, num: 1 },
{ order_id: "2", title: "牛奶", price: 50, num: 1 },
{ order_id: "2", title: "酸奶", price: 40, num: 1 },
{ order_id: "3", title: "礦泉水", price: 2, num: 5 },
{ order_id: "3", title: "毛巾", price: 10, num: 1 }
]);
//=================================
db.order.aggregate([
{
$project:{
order_id:1,
uid:1,
trade_no:1,
all_price:1,
all_num:1
}
},
{
$match:{
all_price:{
$gte:90
}
}
},
{
$sort:{
all_price:-1
}
},
{
$limit:2
},
{
$skip:1
},
{
$lookup:{
from:'order_item', // 要關聯的表
localField:'order_id', //order表中的order_id
foreignField:'order_id', // order_item表中的order_id
as:'items'
}
}
])
//=================================
db.order_item.aggregate([
{
$group:{
_id:'$order_id',total:{
$sum:'$num'
}
}
},
])
//=================================
db.order.aggregate([
{
$lookup:{
from:'order_item', // 要關聯的表
localField:'order_id', //order表中的order_id
foreignField:'order_id', // order_item表中的order_id
as:'items'
}
}
])
查詢一個表作岖,找出商品名稱是酸奶的商品唆垃,酸奶這個商品對應的訂單的訂單號以及訂單總價格。
//先查一個表痘儡,然后獲取出數據辕万,再通過獲取的數據查下一個表
OrderItemModel.find({"_ id":"5b743da92c327f8d1b360546"}, function(err,docs){
// console. log(docs);
var order_item=JSON. parse( JSON. stringify(docs));
var order_id=order_item[0].order_ id;
OrderModel. find({"order_ id":order_ id} 沉删,function(err, order){
//
console. log(order);
order_ item[0] . order. info=order[0];
console. log(order_ item )
})
}
多個表的關聯存儲
這里就是通過輸入id來進行關聯
[圖片上傳失敗...(image-b2baf1-1601889185798)]
//article.js文件
// 文章表渐尿,表結構
var Schrma=mongoose.Schrma;
var ArticleSchema=new Schema({
title:{
type:String,
unique:true
},
cid:{
type:{
type:Schema.Types.ObjectId
},//分類ID
},
author_id:{
type:Schema.Types.ObjectId
},//用戶的id
author_name:{
type:String
},
descripton:String,
content:String
})
//文章分類
var ArticleSchema=new mongoose.Schema({
title:{
type:String,
unique:true
},
addtime:{
type:Date
},
descripton:String,
})
//用戶名
var ArticleSchema=new mongoose.Schema({
username:{
type:String,unique:true
},
password:String,
name:String,
age:Number,
sex:String,
tel:Number,
status:{
type:Number,
default:1
}
})
//分類增加
var cate=new 文章分類({
title:'國內行文',
descripton:'國內行文'
})
cate.save();
//增加用戶
var cate=new 用戶表({
username:'zhangfa ',
password:'nfusdhfk',
name:'sfsdaf',
age:20,
sex:'nan',
tel:20,
status:1
})
cate.save();
//文章表
var cate=new 文章表({
title:'習近平訪問',//國際新新聞
cid:'查找國際新聞的id與他關聯',
author_id:'獲取用戶的id與他關聯',//用戶的id
author_name:"獲取用戶的名與之關聯",
descripton:'我的描述’',
content:'這里面時內容詳情'
})
cate.save();
mongoose實現多個表查詢Populate
mongoose使用關聯查詢的時候,你首先要知道主鍵與外鍵
要使用他之前要在Schema里面定義ref
那個表的key有外鍵那個就是用ref
const articleSchema = new mongoose.Schema({
author: {
type: mongoose.Schema.Types.ObjectId, //要將文章中的作者和用戶中的作者進行關聯
ref: 'User', //這個屬性就是用來將文章集合和用戶集合進行關聯’User‘就是集合的名字
required: [true, '請傳遞作者'],
}
});
//查詢的方法
// 注意要是用populate需要引入用到的Moudel
//說建議用聚合管道查詢
let articles = await pagination(Article)//pagination分頁矾瑰,
.find()//查詢
.page(page)//客戶端傳遞過來的頁碼
.size(2)//顯示幾個
.display(3)//最多
.populate("author") //populate('')這個方法里面存放的就是你要查詢的字段信息
.exec();
增加數據
//實例化Model 通過實例化User 的Molde創(chuàng)建添加數據
var admin = new User({
username: 'admin',
passworld: '123456',
email: 'admin@admin.com'
});
admin.save(function(err, ret) {//里面的兩個方法用來查看是否將數據存進去
if (err) {
console.log('失敗');
} else {
console.log('成功');
console.log(ret);
}
})
一次性寫法:
new student(req.query).save(function(err, user) {
if (err) {
return next(err)
}
res.status(200).json({
err_code: 0,
message: 'OK',
user: user
})
})
查詢數據
? 查詢所有數據:
// ***********************
// #region 查詢數據所有數據
// ***********************
User.find(function(err, ret) {
if (err) {
console.log('失敗');
} else {
console.log(ret);
}
})
按照條件查詢數據(查詢出來的是數組里面存放的是對象):
User.find({
username: '張三'
//年齡大于18去API查
}, function(err, ret) {
if (err) {
console.log('失敗');
} else {
console.log(ret);
}
})
按照條件查詢數據(查詢出來的是數據直接存放在對象中()):
User.findOne({ //如果第一個沒有參數,那么查詢的就是第一個數據
username: '張三', //多個數據直接在后面跟就好了
passworld: '123456'
}, function(err, ret) {
if (err) {
console.log('失敗');
} else {
console.log(ret);
}
})
分析查詢
User.find(function(err, ret) {
if (err) {
console.log('失敗');
} else {
console.log(ret);
}
}).limit(1)//表示輸出第一行數據
user.getIndexes();
查詢方法
mongoose查詢使用最基礎的方法就是find砖茸、findOne方法,前者查詢所有滿足條件的值殴穴,后者取滿足條件的某一個值渔彰。
2、查詢條件
mongoose查詢條件其實就是在find方法的基礎上添加mongodb條件操作符推正,如Thing.find().gt('age', 21)
就等同于Thing.find({age: {$gt: 21}})
恍涂,mongodb條件操作符如下:
$or 或關系db.collection_name.find({$or: [{key1: value1}, {key2: value2}]})
$nor 或關系取反
$gt 大于
$gte 大于等于
$lt 小于
$lte 小于等于
$ne 不等于
$in 在多個值范圍內
$nin 不在多個值范圍內
$all 匹配數組中多個值
$regex 正則,用于模糊查詢
$size 匹配數組大小
$maxDistance 范圍查詢植榕,距離(基于LBS)
$mod 取模運算
$near 鄰域查詢再沧,查詢附近的位置(基于LBS)
$exists 字段是否存在
$elemMatch 匹配內數組內的元素
$within 范圍查詢(基于LBS)
$box 范圍查詢,矩形范圍(基于LBS)
$center 范圍醒詢尊残,圓形范圍(基于LBS)
$centerSphere 范圍查詢炒瘸,球形范圍(基于LBS)
$slice 查詢字段集合中的元素(比如從第幾個之后,第N到第M個元素)
例如
tb_user.findOne({$or:[{user_name:req.body.user_name},{email:req.body.email}]},function(err,ret){
if(err){
console.log(err);
}else{
console.log(ret);
}
})
3寝衫、填充對象
查詢對象時顷扩,對象中存在其他對象的引用,查詢出來的引用對象默認是顯示引用對象的id慰毅,如果需要引用對象的其他屬性就需要使用populate方法填充引用對象隘截。
如果對以上知識點不太了解可以參考:
查詢實例
schema.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
name : { type: String, unique: true },
posts : [{ type: Schema.Types.ObjectId, ref: 'Post' }]
});
var User = mongoose.model('User', UserSchema);
var PostSchema = new Schema({
poster : { type: Schema.Types.ObjectId, ref: 'User' },
comments : [{ type: Schema.Types.ObjectId, ref: 'Comment' }],
title : String,
content : String
});
var Post = mongoose.model('Post', PostSchema);
var CommentSchema = new Schema({
post : { type: Schema.Types.ObjectId, ref: "Post" },
commenter : { type: Schema.Types.ObjectId, ref: 'User' },
content : {
main: String,
label: String
},
points: [
point: [{type: Schema.Types.ObjectId, ref: 'Point'}]
]
});
var Comment = mongoose.model('Comment', CommentSchema);
var PointSchema = new mongoose.Schema({
name: String,
parent: {type: Schema.Types.ObjectId, ref: 'point'},
children: [{type: Schema.Types.ObjectId, ref: 'point'}]
})
var Point = mongoose.model('Point', PointSchema);
1、深層屬性查詢
有些對象結構比較復雜汹胃,屬性可能存在多層嵌套關系婶芭,有時需要通過對象屬性下屬的屬性查詢對象,如通過content的label的值查詢Comment
Comment.find({'content.label': value}, function (err, comment) {
console.log(comment)
})
2着饥、二維數組查詢
如果二維數組結構為[[]]犀农,這樣的數組是可以查詢,但是填充數組里對象時會有問題
Comment.find({'points': value}).populate('points').exec(function (err, comment) {
console.log(comment) // 無法填充points
})
所以需要填充二維數組里的對象時宰掉,不能使用這種結構呵哨,而應該如schema.js中一樣赁濒,將里面的數組先作為對象保存
Comment.find({'points': value}).populate('points.point').exec(function (err, comment) {
console.log(comment) // 無法填充points
})
3、循環(huán)填充
結構如Point孟害,讀取point時拒炎,需要填充children,而childern的childern也需要填充纹坐,使用populate只能填充當前的childern枝冀,在schema.js添加:
PointSchema.pre('find', function(next) {
this.populate('children')
next()
})
這樣每次查詢時舞丛,自動為point填充childern
4耘子、多表聯合查詢
mongoose其實沒有多表聯合查詢的方法,不過我們可以通過多次查詢來實現球切。
通過user的name谷誓、post的content查詢post:
User.find({name: name}, function (err, users) {
Post.find({poster: {$in: users}, content: content}, function (err, posts) {
console.log(posts)
})
})
有時我們也需要對取出來的數據進行再次過濾,而不是通過查詢語句查詢
通過user的name吨凑、post的content捍歪、comment的content.main查詢post:
User.find({name: name}, function (err, users) {
Post.find({poster: {$in: users}, content: content}).populate('commenter').exec(function (err, posts) {
posts.filter(function(post) {
return post.commenter.content.main === value
})
})
})
刪除數據
根據條件刪除所有
User.remove({
username: '張三'
}, function(err, ret) {
if (err) {
console.log('失敗');
}
console.log('成功');
console.log(ret);//所有的張三都刪除了
})
根據條件刪除一個
Model.findOneAndRemove(conditions,[options],[callback])
根據id刪除一個
Model.findByIdAndRemove(id,[options],[callback])
刪除的方法
Model.deleteOne(id,[options],[callback])
更新數據
根據條件更新所有:
//model就是數據表鸵钝,你引入的表名
Model.update(conditions,doc,[options],[callback])
Model.updateOne(conditions,doc,[options],[callback])
根據指定條件更新一個:
Model.findOneAndUpdate([conditions],[update],[options],[callback])
根據id更新一個
// 第一個參數是他的MongoDB的id,第二個參數是你所想要修改的值,第三個是回調函數是否成功的
User.findByIdAndUpdate('5e0749619ca65b30b05a69ca', {
passworld: '123'
}, function(err, ret) {
if (err) {
console.log('失敗');
} else {
console.log('成功');
}
})
Mongodb 對內嵌數組的增刪改查操作
先做一個初始化糙臼,設置一個User類,其初始數據如下:
{ arr: [ 1, 2 ],
_id: 5ac5ee12a79131259413c40f,
name: 'scy',
__v: 0 }
每次以初始數據為基恩商,進行操作变逃。
1、向內嵌數組添加數據
使用操作符 $push怠堪,向數組末尾添加數據 揽乱,可重復
//第一個參數是匹配條件 第二個參數是具體操作
User.update({name:"scy"},{$push:{"arr":3}});//向user里面的arr末尾追加元素3
結果如下:
{ arr: [ 1, 2, 3 ],
_id: 5ac5f0d3db343b1888a8969d, name: 'scy',__v: 0 }
一次添加多個數據
User.update({name:"scy"},{$push:{"arr":{$each:[2,3]}}});
router.get('/tijiao', function(req, res, next) {
student1.find(function(err, ret) {
if (err) {
console.log('失敗');
} else {
var now = new Date();
var nowStr = now.toLocaleString('chinese', { hour12: false });
req.query.data = nowStr;
req.query.changdu = ret.length + 1
new student1(req.query).save(function(err, ret) { //里面的兩個方法用來查看是否將數據存進去
if (err) {
console.log('失敗');
} else {
console.log(req.query);
console.log(ret._id);
//注意就是這里將上一個''引號可以轉換
req.query.sid = ret._id + '';
student.update({ _id: req.query.id }, { $push: { 'shuzu': req.query } }, function(err, ret) {
if (err) {
console.log('失敗');
} else {
console.log('成功');
}
})
res.status(200).json({
err_code: 0,
message: 'OK',
ret: ret,
})
}
})
}
})
})
2、刪除內嵌數組指定數據
注意添加的時候加一個''
引號這樣可以將id轉為字符串
使用操作符 $pull
//刪除arr所有數據為2的元素
User.update({name:"scy"},{$pull:{"arr":2}});
執(zhí)行結果:
{ arr: [ 1 ], _id: 5ac5f39fdad94e23e8de9aee, name: 'scy', __v: 0 }
如果數組元素是對象,可以根據對象屬性操作:
{
name:"scy",
mArray:[{age:13,weight:50},{age:13,weight:30}]
}
User.update({name:"scy"},{$pull:{"mArray":{"weight":30}}});//刪除所有weight屬性值為30的對象
MongoDB,從數組中刪除對象
{
_id: 5150a1199fac0e6910000002,
name: 'some name,
items: [{
id: 23,
name: 'item name 23'
},{
id: 24,
name: 'item name 24'
}]
}
刪除代碼
User.update(
{'_id': ObjectId("5150a1199fac0e6910000002")},
{ $pull: { "items" : { id: 23 } } }
);
3粟矿、修改內嵌數組指定數據
-
數據截圖:
[圖片上傳失敗...(image-e19f7e-1601889185798)]
-
我想更新arr_1數組中凰棉,a = 1 的對象,更新為 {a:11,b:12} 運行更新代碼陌粹,如下:
[復制代碼](javascript:void(0);)
[db.nestedUpdate.updateMany({ 'arr_1.a': 1 }, { $set: { 'arr_1.$.a': 11, 'arr_1.$.b': 12, } }) 也可以:繼續(xù)存 $set: { "shuzu.$.sun8": [{ sun9: req.query.xuehao, sun10: req.query.xuehao, sun11: req.query.xuehao, }, { sun9: req.query.xuehao, sun10: req.query.xuehao, sun11: req.query.xuehao, sun12: '7', }] }
復制代碼](javascript:void(0);)
我暫時還沒找到能批量修改數組元素的方法
1
3撒犀、修改內嵌數組指定數據
我暫時還沒找到能批量修改數組元素的方法
//將數組里面的第一個元素1修改為3
User.update({"arr":{$all:[1]}},{$set:{"arr.$":2}});
//也可以根據下標
User.update({$set:{"arr.1":22}});//將arr下標為1的元素修改為22
如果數組的元素是對象,如下:
1
2
如果數組的元素是對象掏秩,如下:
{
name:"scy",
mArray:[{age:13,weight:50},{age:13,weight:30}]
}
修改操作如下:
User.update({"mArray.age":13},{$set:{"mArray.$.age":22}});//將第一個age為13的值修改為22
//還可以這樣 mArray.1.age 其中1是下標
User.update({$set:{"mArray.1.age":22}});//將arr第二個元素對象的age改為22
批量修改內嵌數組對象
//computer1數據表
//data.$[].network數組下面的數據
computer1.update({'roomNumber': req.query.w}, {$set: {'data.$[].network': 10}}, {multi: true},function(a,s){
console.log(a);
console.log(s);
})
4绘证、查詢內嵌數組并返回指定的數據
使用$size 返回指定數組長度的數據
//$size限制比較大 下面表示查詢數組長度為2的數據
User.find({arr:{$size:2}})
$slice,這個操作符還是比較強大的適合查詢數組中的數據
//匹配到的user 將其數組截取第一個返回 如[1,1,2]返回[1]
User.findOne({name:"scy"},{arr:{$slice:1}});
//將匹配到的user的數組 截取返回后面兩個元素 如[1,1,2]返回[1,2]
User.findOne({name:"scy"},{arr:{$slice:-2}});
//從數組的下表為1的元素開始 返回兩個 如[1,3,2]返回[3,2]
User.findOne({name:"scy"},{arr:{$slice:[1,2]}});
$elemMatch查詢的是某一個數據
用法如下:
User.findOne({name:"scy"},{arr:{$elemMatch:{key:val}});
總的代碼案例如下:
在當前的目錄下的demo.js
文件下
導出導入數據庫
首先要開啟數據庫連接通過mongod --dbpath 數據存儲目錄路徑
我的數據庫目錄地址好像在D:\mongoDB\two
然后在命令行中輸入
導出:
//-h表示主機 -d表示要導出的數據庫 -o輸出的目錄
mongodump -h (主機127.0.0.1) -d (到處的數據庫) -o (地址)
//例如
mongodump -h 127.0.0.1 -d user -o C:\data
導入:
mongorestore -h (主機地址) -d (導入數據庫名) 導入的地址
第二種
8.MongoDB數據庫
8.1 關系型數據庫的非關系型數據庫
表就是關系
或者說表于表之間存在關系。
- 所有的關系型數據庫都需要通過
sql
語言來操作 - 所有的關系型數據庫都需要設計表結構
- 而且數據表還支持約束
- 唯一的
- 主鍵
- 默認值
- 非空
- 非關系型數據庫可以說非常的靈活
- 有的非關系型數據庫就是key-value隊
- 在mingoDB是長得最像關系型數據庫的非關系型數據庫
- 數據庫-》數據庫
- 數據表-》集合(數組)
- 表記錄-》(文檔對象)
- MongoDB不需要設計表結構
- 也就是說你可以任意的往里面存數據哗讥,沒有結構性這么一說
8.2安裝
- 64位下載地址:https://www.mongodb.com/what-is-mongodb
- 32位下載地址:https://www.mongodb.org/dl/win32/i386
- 配置環(huán)境變量
8.3啟動和關閉數據庫
啟動:
# mongodb 默認使用執(zhí)行 mongdb 命令所處盤符根目錄下的/data/db 作為自己的數據存儲目錄
# 啟動的時候出現問題下面這張圖的問題
#需要在第一次執(zhí)行該命令之前先手動見一個 [c,d,盤]/data/db
在cmd中輸入mongodb
[圖片上傳失敗...(image-421fc9-1601889185798)]
如果想要修改默認數據存儲目錄嚷那,可以:
mongod --dbpath=數據存儲目錄路徑
停止:
在開啟服務的控制臺,直接Ctrl+c即可停止
或者直接關閉開啟服務的控制臺也可以杆煞。
8.4連接數據庫
#該命令默認連接本機的MongoDB服務
mongo
退出連接:
#在連接狀態(tài)輸入exit退出連接
exit
8.5基本命令
-
show dbs
(查看顯示所有的數據庫) - db (查看當前操作的數據庫)
-
use 數據庫名稱
(切換到指定數據【如果沒有會新建】) - 插入數據
8.6在Node中如何操作MongoDB數據
8.6.1使用官方的mongodb包來操作
https://github.com/mongodb/node-mongodb-native#installation
8.6.2使用第三方的mongodb來操作Mongodb數據庫
第三方包:Mongodb
基于Mongodb官方的mongodb
包再一次做了封裝
第三方包連接數據庫
安裝:
npm i mongoose
#注意先下載npm i -y (如果有就不需要下載了)然后下載mongoose第三方的包
const mongoose = require('mongoose'); //引入mongoose包
//連接MongoDB數據庫
mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true });
// 這句先不了解
mongoose.Promise = global.Promise;
//創(chuàng)建一個模型
// 就是在設計數據庫
// MongoDB是動態(tài)的,非常靈活,只需要在代碼中設計你的數據庫就可以了
// mongodb這個包就可以讓你的設計編寫過程變的非常簡單
const Cat = mongoose.model('Cat', { name: String });
// 實例化一個Kitty
const kitty = new Cat({ name: 'Zildjian' });
// 持久化保存kitty實例
kitty.save().then(() => console.log('meow'));
持久化存儲for:
const mongoose = require('mongoose'); //引入mongoose包
// //連接MongoDB數據庫
mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true });
// // 這句先不了解
mongoose.Promise = global.Promise;
var Cat = mongoose.model('Cat', { name: String });
for (var i = 0; i < 50; i++) {
var kitty = new Cat({ name: '喵喵' + i });
kitty.save(function(err) {
if (err) {
console.log(err);
}
console.log('meow');
})
}
1.MongoDB數據庫的基本概念
- 數據庫
- 一個數據庫中有多個集合(表)
- 一個集合中可以有多個文檔(表記錄)
- 文檔結構靈活魏宽,沒有任何限制
- MongoDB非常靈活众雷,不像MySQL一樣要先創(chuàng)建數據庫脐湾,表,設計表結構
- 在這里:當你需要插入數據的時候,只需要指定往那個數據庫那個集合操作就可以
- 一切都由MongoDB來幫你自動完成建庫建表這件事
{
qq:{
//users:[{'這里存的是每一條記錄'對象}],//一個對象教文檔偿渡,要有一些約定,要不然亂
users:[
{},
{}
]
products:[
{name:'張三',age:15},
{name:'李四',age:16},
{name:'王五',age:17},
{name:'張三123',age:18},
...
]
},
taobao:{
},
baidu:{
}
}
mongoDB的案例構建(案例案例)
設計Scheme發(fā)布Model
這些增刪改查的方法都是根據引入的包是var mongoose = require('mongoose');方法進行的
與菜鳥聯盟的方法不同的原因是引入的包不同
var mongoose = require('mongoose');
// 獲取他的結構
var Schema = mongoose.Schema;
// 指定連接的數據庫不需要存在,當你插入第一條數據之后就會自動被創(chuàng)建出來
// 1.連接數據庫
mongoose.connect('mongodb://localhost:27017/itcast', { useNewUrlParser: true });
// 2.設計集合結構
// 字段名稱就是表結構中的屬性名稱
// 值
// 約束的目的是為了保證數據的完整性,不要有臟數據
// 架構就是設置他的類型,必須要有的數據
var userSchema = new Schema({
username: {
type: String,
required: true //必須有不能為空
},
passworld: {
type: String,
required: true
},
email: {
type: String,
default:寫什么都可以//default表示默認的
enum:[0,1]//這個表示可選的必須在這兩個中選擇一個
}
})
// 3.將文檔結構發(fā)布為模型
// mongoose.model()方法就是用來將一個架構發(fā)布為model
// 第一個參數:傳入一個一個大寫名詞單數字符串用來表示你的數據庫名稱
// mongoose會自動將大寫名詞的字符串生成小寫復數的集合名稱
// 例如這里的User最終會變?yōu)閡sers集合名稱
// 第二個參數:模型構造函數
var User = mongoose.model('User', userSchema); //第一個參數是字符串,第二個參數是一個架構
// 4.當我們有了模型構造韓素華之后,就可以使用這個構造函數對users集合中的數據進行(增刪改查)
增加數據
var admin = new User({
username: 'admin',
passworld: '123456',
email: 'admin@admin.com'
});
admin.save(function(err, ret) {//里面的兩個方法用來查看是否將數據存進去
if (err) {
console.log('失敗');
} else {
console.log('成功');
console.log(ret);
}
})
一次性寫法:
new student(req.query).save(function(err, user) {
if (err) {
return next(err)
}
res.status(200).json({
err_code: 0,
message: 'OK',
user: user
})
})
查詢數據
? 查詢所有數據:
// ***********************
// #region 查詢數據所有數據
// ***********************
User.find(function(err, ret) {
if (err) {
console.log('失敗');
} else {
console.log(ret);
}
})
按照條件查詢數據(查詢出來的是數組里面存放的是對象):
User.find({
username: '張三'
//年齡大于18去API查
}, function(err, ret) {
if (err) {
console.log('失敗');
} else {
console.log(ret);
}
})
按照條件查詢數據(查詢出來的是數據直接存放在對象中()):
User.findOne({ //如果第一個沒有參數,那么查詢的就是第一個數據
username: '張三', //多個數據直接在后面跟就好了
passworld: '123456'
}, function(err, ret) {
if (err) {
console.log('失敗');
} else {
console.log(ret);
}
})
分析查詢
User.find(function(err, ret) {
if (err) {
console.log('失敗');
} else {
console.log(ret);
}
}).limit(1)//表示輸出第一行數據
user.getIndexes();
刪除數據
根據條件刪除所有
User.remove({
username: '張三'
}, function(err, ret) {
if (err) {
console.log('失敗');
}
console.log('成功');
console.log(ret);//所有的張三都刪除了
})
根據條件刪除一個
Model.findOneAndRemove(conditions,[options],[callback])
根據id刪除一個
Model.findByIdAndRemove(id,[options],[callback])
更新數據
根據條件更新所有:
Model.update(conditions,doc,[options],[callback])
根據指定條件更新一個:
Model.findOneAndUpdate([conditions],[update],[options],[callback])
根據id更新一個
// 第一個參數是他的MongoDB的id,第二個參數是你所想要修改的值,第三個是回調函數是否成功的
User.findByIdAndUpdate('5e0749619ca65b30b05a69ca', {
passworld: '123'
}, function(err, ret) {
if (err) {
console.log('失敗');
} else {
console.log('成功');
}
})
Mongodb 對內嵌數組的增刪改查操作
先做一個初始化堆缘,設置一個User類,其初始數據如下:
{ arr: [ 1, 2 ],
_id: 5ac5ee12a79131259413c40f,
name: 'scy',
__v: 0 }
每次以初始數據為基送膳,進行操作员魏。
1、向內嵌數組添加數據
使用操作符 $push叠聋,向數組末尾添加數據 撕阎,可重復
//第一個參數是匹配條件 第二個參數是具體操作
User.update({name:"scy"},{$push:{"arr":3}});//向user里面的arr末尾追加元素3
結果如下:
{ arr: [ 1, 2, 3 ],
_id: 5ac5f0d3db343b1888a8969d, name: 'scy',__v: 0 }
一次添加多個數據
User.update({name:"scy"},{$push:{"arr":{$each:[2,3]}}});
router.get('/tijiao', function(req, res, next) {
student1.find(function(err, ret) {
if (err) {
console.log('失敗');
} else {
var now = new Date();
var nowStr = now.toLocaleString('chinese', { hour12: false });
req.query.data = nowStr;
req.query.changdu = ret.length + 1
new student1(req.query).save(function(err, ret) { //里面的兩個方法用來查看是否將數據存進去
if (err) {
console.log('失敗');
} else {
console.log(req.query);
console.log(ret._id);
//注意就是這里將上一個''引號可以轉換
req.query.sid = ret._id + '';
student.update({ _id: req.query.id }, { $push: { 'shuzu': req.query } }, function(err, ret) {
if (err) {
console.log('失敗');
} else {
console.log('成功');
}
})
res.status(200).json({
err_code: 0,
message: 'OK',
ret: ret,
})
}
})
}
})
})
2、刪除內嵌數組指定數據
注意添加的時候加一個''
引號這樣可以將id轉為字符串
使用操作符 $pull
//刪除arr所有數據為2的元素
User.update({name:"scy"},{$pull:{"arr":2}});
執(zhí)行結果:
{ arr: [ 1 ], _id: 5ac5f39fdad94e23e8de9aee, name: 'scy', __v: 0 }
如果數組元素是對象,可以根據對象屬性操作:
{
name:"scy",
mArray:[{age:13,weight:50},{age:13,weight:30}]
}
User.update({name:"scy"},{$pull:{"mArray":{"weight":30}}});//刪除所有weight屬性值為30的對象
MongoDB,從數組中刪除對象
{
_id: 5150a1199fac0e6910000002,
name: 'some name,
items: [{
id: 23,
name: 'item name 23'
},{
id: 24,
name: 'item name 24'
}]
}
刪除代碼
User.update(
{'_id': ObjectId("5150a1199fac0e6910000002")},
{ $pull: { "items" : { id: 23 } } }
);
3碌补、修改內嵌數組指定數據
-
數據截圖:
[圖片上傳失敗...(image-614047-1601889185798)]
-
我想更新arr_1數組中虏束,a = 1 的對象,更新為 {a:11,b:12} 運行更新代碼厦章,如下:
[復制代碼](javascript:void(0);)
[db.nestedUpdate.updateMany({ 'arr_1.a': 1 }, { $set: { 'arr_1.$.a': 11, 'arr_1.$.b': 12, } }) 也可以:繼續(xù)存 $set: { "shuzu.$.sun8": [{ sun9: req.query.xuehao, sun10: req.query.xuehao, sun11: req.query.xuehao, }, { sun9: req.query.xuehao, sun10: req.query.xuehao, sun11: req.query.xuehao, sun12: '7', }] }
復制代碼](javascript:void(0);)
我暫時還沒找到能批量修改數組元素的方法
1
3镇匀、修改內嵌數組指定數據
我暫時還沒找到能批量修改數組元素的方法
//將數組里面的第一個元素1修改為3
User.update({"arr":{$all:[1]}},{$set:{"arr.$":2}});
//也可以根據下標
User.update({$set:{"arr.1":22}});//將arr下標為1的元素修改為22
如果數組的元素是對象,如下:
1
2
如果數組的元素是對象袜啃,如下:
{
name:"scy",
mArray:[{age:13,weight:50},{age:13,weight:30}]
}
修改操作如下:
User.update({"mArray.age":13},{$set:{"mArray.$.age":22}});//將第一個age為13的值修改為22
//還可以這樣 mArray.1.age 其中1是下標
User.update({$set:{"mArray.1.age":22}});//將arr第二個元素對象的age改為22
批量修改內嵌數組對象
//computer1數據表
//data.$[].network數組下面的數據
computer1.update({'roomNumber': req.query.w}, {$set: {'data.$[].network': 10}}, {multi: true},function(a,s){
console.log(a);
console.log(s);
})
4汗侵、查詢內嵌數組并返回指定的數據
使用$size 返回指定數組長度的數據
//$size限制比較大 下面表示查詢數組長度為2的數據
User.find({arr:{$size:2}})
$slice,這個操作符還是比較強大的適合查詢數組中的數據
//匹配到的user 將其數組截取第一個返回 如[1,1,2]返回[1]
User.findOne({name:"scy"},{arr:{$slice:1}});
//將匹配到的user的數組 截取返回后面兩個元素 如[1,1,2]返回[1,2]
User.findOne({name:"scy"},{arr:{$slice:-2}});
//從數組的下表為1的元素開始 返回兩個 如[1,3,2]返回[3,2]
User.findOne({name:"scy"},{arr:{$slice:[1,2]}});
$elemMatch查詢的是某一個數據
用法如下:
User.findOne({name:"scy"},{arr:{$elemMatch:{key:val}});
總的代碼案例如下:
在當前的目錄下的demo.js
文件下
嵌套管道查詢
const SurveySchema = new Schema({
_id:{ type: Schema.ObjectId, auto: true },
name: String,
enabled: {type: Boolean, Default: true},
created_date:{type: Date, Default: Date.now},
company: {type: Schema.Types.ObjectId, ref: 'Company'},});
const GroupSchema = new Schema({
_id:{ type: Schema.ObjectId, auto: true },
name: String,
order: String,
created_date:{type: Date, Default: Date.now},
questions: [{type: Schema.Types.ObjectId, ref: 'Question'}],
survey: {type: Schema.Types.ObjectId, ref: 'Survey'}
});
const ResponseSchema = new Schema({
_id:{ type: Schema.ObjectId, auto: true },
response_text: String,
order: String,
created_date:{type: Date, Default: Date.now},
question:{type: Schema.Types.ObjectId, ref: 'Question'}
});
Survey.aggregate([
{ $match: {} },
{ $lookup: {
from: 'groups',
localField: '_id',
foreignField: 'survey',
as: 'groupsofquestions',
}},
{ $unwind: {
path: "$groupsofquestions",
preserveNullAndEmptyArrays: true
}},
{ $lookup: {
from: 'questions',
localField: 'groupsofquestions._id',
foreignField: 'group',
as: 'questionsofgroup',
}},
{ $lookup: {
from: 'response',
localField: 'questionsofgroup._id',
foreignField: 'question',
as: 'responses',
}},
{ $group: {
_id: "$_id",
name: {$first: "$name"},
groups: {$push: {
id: "$groupsofquestions._id",
name: "$groupsofquestions.name",
questions: "$questionsofgroup",
reponses: "$responses"
}}
}}
])
aggregate()
語 法 \color{red}{語法}語法
db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION);
1
數 據 \color{red}{數據}數據
數據使用菜鳥教程的數據啦????
/* 1 */
{
"_id" : ObjectId("5e86e29788e64443e448dfc0"),
"title" : "MongoDB Overview",
"description" : "MongoDB is no sql database",
"by_user" : "runoob.com",
"url" : "http://www.runoob.com",
"tags" : [
"mongodb",
"database",
"NoSQL"
],
"likes" : 100
}
/* 2 */
{
"_id" : ObjectId("5e86e2ad88e64443e448dfd2"),
"title" : "NoSQL Overview",
"description" : "No sql database is very fast",
"by_user" : "runoob.com",
"url" : "http://www.runoob.com",
"tags" : [
"mongodb",
"database",
"NoSQL"
],
"likes" : 10
}
/* 3 */
{
"_id" : ObjectId("5e86e2bc88e64443e448dfd7"),
"title" : "Neo4j Overview",
"description" : "Neo4j is no sql database",
"by_user" : "Neo4j",
"url" : "http://www.neo4j.com",
"tags" : [
"neo4j",
"database",
"NoSQL"
],
"likes" : 750
}
1234567891011121314151617181920212223242526272829303132333435363738394041424344
管 道 操 作 符 \color{red}{管道操作符}管道操作符
操作符 | 含義 |
---|---|
$group | 將collection中的document分組,可用于統(tǒng)計結果 |
$match | 過濾數據囊骤,只輸出符合結果的文檔 |
$project | 修改輸入文檔的結構(例如重命名晃择,增加、刪除字段也物,創(chuàng)建結算結果等) |
$sort | 將結果進行排序后輸出 |
$limit | 限制管道輸出的結果個數 |
$skip | 跳過制定數量的結果宫屠,并且返回剩下的結果 |
$unwind | 將數組類型的字段進行拆分 |
表 達 式 操 作 符 \color{red}{表達式操作符}表達式操作符
操作符 | 含義 | 實例 |
---|---|---|
$sum | 計算總和,{$sum : 1}表示返回總和×1的值(即總和的數量),使用{$sum : '$制定字段' }也能直接獲取制定字段的值的總和 |
db.collection.aggregate([{$group : {_id : "$by_user", content_sum : {$sum : "$likes"}}}]) |
$avg | 平均值 | db.collection.aggregate([{$group : {_id : "$by_user", content_sum : {$avg : "$likes"}}}]) |
$min | 獲取集合中所有文檔對應值得最小值 | db.collection.aggregate([{$group : {_id : "$by_user", content_sum : {$min : "$likes"}}}]) |
$max | 獲取集合中所有文檔對應值得最大值 | db.collection.aggregate([{$group : {_id : "$by_user", content_sum : {$max : "$likes"}}}]) |
$push | 在結果文檔中插入值到一個數組中 | db.collection.aggregate([{$group : {_id : "$by_user", url : {$push : "$url"}}}]) |
$addToSet | 在結果文檔中插入值到一個數組中滑蚯,但不創(chuàng)建副本 | db.collection.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}]) |
$first | 根據資源文檔的排序獲取第一個文檔數據 | db.collection.aggregate([{$group : {_id : "$by_user", url : {$first : "$url"}}}]) |
$last | 根據資源文檔的排序獲取最后一個文檔數據 | db.collection.aggregate([{$group : {_id : "$by_user", url : {$last : "$url"}}}]) |
具 體 例 子 \color{skyblue}{具體例子}具體例子
-
$group
-
簡單闡述
//將document分組浪蹂,用作統(tǒng)計結果 db.collection.aggregate([ // aggregate方法接收的是一個數組 { $group: { // _id字段表示要基于哪個字段來進行分組(即制定字段值相同的為一組) // $by_user表示要基于$by_user字段來進行分組 _id: '$by_user', // content_sum字段的值$sum: 1表示的是獲取滿足by_user字段相同的這一組的數量乘以后面給定的值(本例為1,那么就是同組的數量)告材。 content_sum: {$sum: 1} } } ]) 123456789101112
-
具體案例
通過以上集合計算每個作者所寫的文章數(通過字段
by_user
字段對數據進行分組坤次,并計算by_user
字段相同值的總和),使用aggregate()
計算結果如下:router.get('/getInfo',async(req, res)=>{ let data=await Content.aggregate([ { $group:{ _id:'$by_user', content_sum:{$sum:1} } } ]) res.json({data}) }) 1234567891011
在這里插入圖片描述
-
-
$match
獲取
likes
的值在50-200
之間的數據:router.get('/getInfo', async (req, res) => { let data = await Content.aggregate([{ $match: { likes: { $gt: 50, $lte: 200 } } }, { $group: { _id: '$_id', content_sum: { $sum: 1 } } } ]) res.json({ data }) }) 12345678910111213141516171819202122
在這里插入圖片描述從圖中可以看出
likes
的值在50-200
之間的數據只有1條斥赋,現在我們只知道這條數據的_id缰猴,如果想知道這條數據的具體信息時應該如何操作呢?上面的表格中提到$project
修改輸入文檔的結構(例如重命名,增加疤剑、刪除字段滑绒,創(chuàng)建結算結果等)闷堡,所以一起來看看吧?????? -
$project
router.get('/getInfo', async (req, res) => { let data = await Content.aggregate([ { $match: { likes: { $gt: 50, $lte: 200 } } }, { //以下的值可以寫$+字段,也可以使用0 和1來表示疑故,若要顯示字段則為1杠览,否則為0 //$project:{_id:'$_id',title:"$title",description:"$description",by_user:"$by_user",url:'$ulr',tags:'$tags',likes:'$likes'} $project:{_id:1,title:1,description:1,by_user:1,url:1,tags:1,likes:1} } ]) res.json({ data }) }) 12345678910111213141516
在這里插入圖片描述 -
以上3個操作符的綜合使用
如果想拿到所有
likes>=10
的document的by_user
字段可以把管道搭配起來用:router.get('/getInfo', async (req, res) => { let data = await Content.aggregate([{ $match: { likes: { $gt: 10 } } }, // 注意$project與$group的順序,換位置后數據為空 { $project: { _id: 0, //_id不顯示 by_user: 1 //by_user顯示 } }, { $group: { _id: null, gameName: { $push: '$by_user' } } } ]) res.json({ data }) }) 12345678910111213141516171819202122232425262728
在這里插入圖片描述 -
$sort
-
根據
likes
進行降序排序router.get('/getInfo', async (req, res) => { let data = await Content.aggregate([ { $project: { _id: 1, by_user: 1, title: 1, title: 1, description: 1, url: 1, tags: 1, likes: 1 } }, { $sort: { likes: -1 } }, ]) res.json({ data }) }) 12345678910111213
在這里插入圖片描述 -
根據
likes
進行升序排序router.get('/getInfo', async (req, res) => { let data = await Content.aggregate([ { $project: { _id: 1, by_user: 1, title: 1, title: 1, description: 1, url: 1, tags: 1, likes: 1 } }, { $sort: { likes: 1 } }, ]) res.json({ data }) }) 12345678910111213
在這里插入圖片描述
-
-
skip
router.get('/getInfo', async (req, res) => { let data = await Content.aggregate([ { $project: { _id: 1, by_user: 1, title: 1, title: 1, description: 1, url: 1, tags: 1, likes: 1 } }, { $sort: { likes: 1 } }, { $skip:1 }, { $limit:1 } ]); res.json({ data }) }) 1234567891011121314151617181920
在這里插入圖片描述 -
$unwind
$unwind管道以document中的數組類型的字段進行拆分,每條包含數組中的一個值纵势。
比如拆分
likes:10
這條數據踱阿,先來看看整體數據信息吧:{ "_id" : ObjectId("5e86e2ad88e64443e448dfd2"), "title" : "NoSQL Overview", "description" : "No sql database is very fast", "by_user" : "runoob.com", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 10 } 12345678910111213
在
tags
數組中有3條數據,所以拆分后會顯示3條數據钦铁,看看具體實現吧:router.get('/getInfo', async (req, res) => { let data = await Content.aggregate([ { $match: { likes: 10 } }, { $unwind:'$tags' }, { $project: { _id: 1, by_user: 1, title: 1, title: 1, description: 1, url: 1, tags: 1, likes: 1 } }, ]) res.json({ data }) }) 123456789101112131415161718
在這里插入圖片描述