一 基础了解
对应关系 -> https://docs.mongodb.com/manual/reference/sql-comparison/
database -> database
collection -> table
document -> row //无模式
field -> column
--------------------------------------------------------------------------------------
使用数据库
use 数据库名称
创建数据库并创建集合myNewCollection1插入数据
use myNewDB
db.myNewCollection1.insertOne( { x: 1 } )
--------------------------------------------------------------------------------------
创建集合并插入数据
db.myNewCollection22.insertOne( { xxx: 1 } )
固定大小集合 capped collection 先进先出
创建一个集合x1 是上限集合,大小200字节 最大2个document,先进先出
也可以不指定document大小db.createCollection("x1", { capped : true, size : 200} )
db.createCollection("x1", { capped : true, size : 200, max : 2 } )
检查是否为上限集合 false true
db.collection.isCapped()
返回集合有多少document
db.collection.count()
转换为上限集合
db.runCommand({"convertToCapped": "collection", size: 100000});
查看collection并升序转换成数组输出,降序 -1
printjson(db.collection.find().sort({$natural:1}).toArray())
collection methods ->
https://docs.mongodb.com/manual/reference/method/js-collection/
--------------------------------------------------------------------------------------
BSON Types
插入数据为undefined
db.collection.insert({x:undefined})
查找需要
db.getCollection('a001').find({x:undefined})//错误
db.getCollection('a001').find({x:{$type:6}})
db.getCollection('a001').find({x:{$type:"undefined"}})
详情:$type对应Number https://docs.mongodb.com/manual/reference/bson-types/
_id 5d89674154e8289fdac72ea5 十六进制
八位 5d896741 表示时间 十进制 1569285953 北京时间 2019/9/24 8:45:53
十位 54e8289fda 随机数 十进制 364672229338
六位 c72ea5 计数器从随机数开始 十进制 13053605
16 -> 10 进制 https://tool.lu/hexconvert/
时间戳 -> 北京时间 https://tool.chinaz.com/Tools/unixtime.aspx
二 基本查询操作
写在一起中间无换行表示同一个效果
// db.people.insertOne( {//插入并创建表
// user_id: "abc123",
// age: 55,
// status: "A"
// } )
// db.people.createIndex( { user_id: 1 } )//创建 增索引
// db.people.createIndex( { user_id: 1, age: -1 } )//创建 增索引 和 减索引
// db.people.drop()//删除表
// db.people.updateMany(//设置列 join_date 内容为当前时间,列没有就添加
// { },
// { $set: { join_date: new Date() } }
// )
// db.people.updateMany(//删除所有列 join_date
// { },
// { $unset: { "join_date": "" } }
// )
// db.people.insertOne(//插入一条数据
// { user_id: "bcd001", age: 45, status: "A" }
// )
// db.people.find()//查询所有数据
// db.people.find(//只查询三个字段 _id user_id status
// { },
// { user_id: 1, status: 1 }
// )
// db.people.find(//只查询两个字段 user_id status
// { },
// { user_id: 1, status: 1, _id: 0 }
// )
// db.people.find(//查询状态不等于A
// { status: { $ne: "A" } }
// )
// db.people.find(//查询status="A" AND age=50
// { status: "A",
// age: 50 }
// )
// db.people.find(//查询status="A" OR age=50
// { $or: [ { status: "A" } , { age: 50 } ] }
// )
// db.people.find(// >25
// { age: { $gt: 25 } }
// )
// db.people.find(// <25
// { age: { $lt: 25 } }
// )
// db.people.find(// >25 <=50
// { age: { $gt: 25, $lte: 50 } }
// )
// db.people.find( { user_id: /abc/ } )// LIKE '%abc%'
// db.people.find( { user_id: { $regex: /abc/ } } )
// db.people.find( { user_id: /^abc/ } )// LIKE 'abc%'
// db.people.find( { user_id: { $regex: /^abc/ } } )
// db.people.find( { status: "A" } ).sort( { user_id: 1 } )//ASC
// db.people.find( { status: "A" } ).sort( { user_id: -1 } )//DESC
// db.people.count()// count(*)
// db.people.find().count()
// db.people.count( { user_id: { $exists: true } } )// 含有user_id的所有count(*)
// db.people.find( { user_id: { $exists: true } } ).count()
// db.people.count( { age: { $gt: 500 } } )//age>500的count(*)
// db.people.find( { age: { $gt: 500 } } ).count()
// db.people.aggregate( [ { $group : { _id : "$status" } } ] )//安装status分组,查询别名_id 只查询status
// db.people.distinct( "status" )//返回一个数组 ["A","B","C","CCCC"]
// db.people.findOne()//查询第一条
// db.people.find().limit(1)
// db.people.find().limit(5).skip(10)//查询大于第 11 12 13 14 15条,如果没有14 15 就显示 11 12 13
// db.people.updateMany(//更新年龄大于5555的状态设置为CCCC
// { age: { $gt: 5555 } },
// { $set: { status: "CCCC" } }
// )
// db.people.updateMany(//更新状态为CCCC的设置
// { status: "CCCC" } ,
// { $inc: { age: 3 } }
// )
// db.people.deleteMany( { status: "D" } )//删除状态为D的所有数据
// db.people.deleteMany({})//清空表数据
三 查询
查询
比较查询操作符 -> https://docs.mongodb.com/manual/reference/operator/query-comparison/
$eq -> = -> { : { $eq: } }
$ne -> != -> {field: {$ne: value} }
$gt -> > -> { field: { $gt: value} }
$gte -> >= -> { field: { $gte: value} }
$lt -> < -> { field: { $lt: value} }
$lte -> <= -> { field: { $lte: value} }
有一个就可以
$in -> in -> { field: { $in: [, , ... ] } }
都没有才可以
$nin -> not in -> { field: { $nin: [ , ... ]} }
--------------------------------------------------------------------------------------
逻辑查询操作符 -> https://docs.mongodb.com/manual/reference/operator/query-logical/
第一个false 余下不执行
$and -> and -> { $and: [ { }, { } , ... , { } ] }
$or -> or -> { $or: [ { }, { }, ... , { } ] }
对or的结果取反
$nor -> not or -> { $nor: [ { }, { }, ... { } ] }
对符合的结果取反
$not -> not -> { field: { $not: { } } }
--------------------------------------------------------------------------------------
元素查询操作符 -> https://docs.mongodb.com/manual/reference/operator/query-element/
$exists -> exists -> { field: { $exists: true/false } }
$type -> { field: { $type: [ , , ... ] } }
// { field: { $type: "string" } }
// { field: { $type: ["string","int"] } }
--------------------------------------------------------------------------------------
评估查询操作符 -> https://docs.mongodb.com/manual/reference/operator/query-evaluation/
// 根据表达式来匹配数据
$expr -> { $expr: { } }
// 根据schema来匹配 required必须含有,properties属性,bsonType类型
$jsonSchema -> { $jsonSchema: }
这里匹配 如果field=0,1,2,3,4,5 v1=2 v2=1 表示除2余1的数,所以是1 3 5
$mod -> { field: { $mod: [ v1, v2 ] } }
匹配正则表达式
{filed:{$regex:/a/}} -> 只要含有a,区分大小写
{filed:{$regex:/^a/}} -> 第一个字母是a,区分大小写
$regex -> 通常用 方式3
{ : { $regex: /pattern/, $options: '' } }//方式1
{ : { $regex: 'pattern', $options: '' } }//方式2
{ : { $regex: /pattern/ } }//方式3
全文检索,不支持中文,根据索引进行匹配,
$text -> 例如 { $text: { $search: "coffee" } } 查找含有coffee的
非常强大 支持js
$where
例如
db.x.find({
$where:function(){
return this.item=="ijk123"&&this.qty==3 //this表示document(行)
}
})
--------------------------------------------------------------------------------------
数组查询操作符 -> https://docs.mongodb.com/manual/reference/operator/query-array/
必须所有的值都要有,$in则表示只有一个就可以
$all -> { : { $all: [ , ... ] } }
只要匹配一个满足就可以
$elemMatch -> { : { $elemMatch: { , , ... } } }
例如:
{ results: { $elemMatch: { $gte: 80, $lt: 85 } } }
{ results: { $elemMatch: { product: "xyz", score: { $gte: 8 } } } }
根据数组大小匹配
$size ->
匹配数组大小为2的,两个效果相同
{ field: { $size: 2 } }
{$where:function(){return this.field.length==2}}
四 更新
更新
db.collection.update({},{$set:{"a":1}})更新第一条
db.collection.updateMany({},{$set:{"a":1}})更新全部
自动更新操作符 -> https://docs.mongodb.com/manual/reference/operator/update-field/
$inc -> { $inc: { : , : , ... } }
{},{$inc:{"age":1,"c":-2,"h.g":2}}//age+1 c-2 h.g+2 字段不存在会创建0+数值
$mul -> { $mul: { : , ... } }
{},{$mul:{"age":5,"h":-1}}//age*5 h*(-1) 数值也可为小数,字段不存在会创建为0*数值
新值最小 就更新
$min -> { $min: { : , ... } }
新值最大 就更新
$max -> { $max: { : , ... } }
$rename -> {$rename: { : , : , ... } }
{},{$rename:{"age":"age1","my.doc":"c.h"}}//更新字段 age -> age1 my.doc -> c.h
$set -> { $set: { : , ... } }
//如果不存在_id:1 不会做任何反应,如果存在,则会字段重新赋值,不存在的字段会添加
{_id:1},{$set:{"a":1,"h.g":2}}
$unset -> { $unset: { : "", ... } }
{},{$unset:{"a":""}}//字段a后面设置"" 这里就删除了字段a,不论a是什么类型
$setOnInsert ->
db.collection.update(
,
{ $setOnInsert: { : , ... } },
{ upsert: true }
)
例如:
db.collection.update(//collection为空 会插入一个文档,并且设置一条 _id:1 c1:apple c2:100
{ _id: 1 },
{
$set: { c1: "apple" },
$setOnInsert: { c2: 100 }
},
{ upsert: true }
)
$currentDate -> { $currentDate: { : , ... } }
也可以把 date 换成 timestamp 字符戳
{},{$currentDate:{mydate:{$type:"date"}}}
五 数组
数组
$ -> { ".$" : value }
可以作为占位符 表示一个 //_id=1 grades=80的把 grade.$ 改为999 只能改一条,改第一个
{ _id: 1, grades: 80 },
{ $set: { "grades.$" : 999 } }
{ "_id" : 1, "grades" : [ 85, 80, 80 ] } -> { "_id" : 1, "grades" : [ 85, 999, 80 ] }
$[] -> { : { ".$[]" : value } }
可以做占位符 表示全部
{_id:1},{$inc:{"sz.$[]":3}}
{_id:1,sz:[1,2,3]} -> {_id:1,sz:[4,5,6]}
$[diy] -> 这里的diy可以随便改 就是一个标识符
{},{$set:{"sz.$[x]":777}},{arrayFilters:[{"$[x]":{$eq:3}}]}
{"_id:1","sz":[3,5,3]}
{"_id:2","sz":[3,3,8]}
{"_id:1","sz":[777,5,777]},
{"_id:2","sz":[777,777,8]}
$addToSet -> { $addToSet: { : , ... } }
将元素添加数组
{_id:1},{$addToSet:{"sz":"3"}} ->{"sz":["1","2"]} ->{"sz":["1","2","3"]}
{_id:1},{$addToSet:{"sz":["4","5"]}} ->{"sz":["1","2"]} ->{"sz":["1","2",["4","5"]]}
$pop -> { $pop: { : <-1 | 1>, ... } }
{_id:1},{$pop:{"sz":-1}}//移除数组第一个
{_id:1},{$pop:{"sz":1}}//移除数组最后一个
$pull -> { $pull: { : , : , ... } }
字段后面跟条件
{ _id: 1 }, { $pull: { scores: {$in:[0,5]} } }//自定义删除所有 0和5
{ _id: 1 }, { $pull: { scores: {$gt:7} } }//删除大于7的
$pullAll -> { $pullAll: { : [ , ... ], ... } }
删除数组所有的 0 和 5
{ _id: 1 }, { $pullAll: { scores: [ 0, 5 ] } }
$push -> { $push: { : , ... } }
{_id:1},{$push:{"sz":3}} -> {"sz":[1,2]} -> {"sz":[1,2,3]}//单个添加
{_id:1},{$push:{"sz":[4,5]}} -> {"sz":[1,2]} -> {"sz":[1,2,[4,5]]}//整体添加单个数组
{_id:1},{$push:{"sz":{$each:[4,5]}}} -> [1,2] -> [1,2,4,5]//批量添加
{_id:1},{$push:{"sz":{$each:[],$sort:1}}} -> [2,1,3] -> [1,2,3]//数组排序 1升序 -1降序
{_id:1},{$push:{"sz":{$each:[8,2],$sort:1}}} -> [2,1,3] -> [1,2,,2,3,8]//添加+排序
{_id:1},{$push:{"sz":{$each:[5,6],$sort:1,$slice:3}}}
原数据 -> 添加 -> 排序(1升序 -1降序) -> 截取(3前三条 -3后三条)
[2,1,3] -> [2,1,3,5,6] ->[1,2,3,5,6] ->[1,2,3]
$each
{ $addToSet: { : { $each: [ , ... ] } } }
{ $push: { : { $each: [ , ... ] } } }
{_id:1},{$addToSet:{"sz":{$each:[4,5]}}}// [2,1] -> [2,1,4,5]
{_id:1},{$push:{"sz":{$each:[4,5]}}}// [2,1] -> [2,1,4,5]
$slice 截取 -> 配合$push $each一起使用
{_id:1},{$push:{"sz":{$each:[8,6],$slice:3}}}
[1,2] -> [1,2,8]// 3前三条 -3后三条 0清空数组
$sort 排序 -> 配合$push $each一起使用
{_id:1},{$push:{"sz":{$each:[8,6],$sort:1}}}
[1,2] -> [1,2,6,8]// 1升序 -1降序
$position 插入位置 -> 配合$push $each一起使用
{_id:1},{$push:{"sz":{$each:[9],$position:1}}}
[3,5,8] -> [3,1,5,8]
1表示在第一个元素后面追加 0表示在开头添加 大于元素个数表示在最后追加
六 增删改查
增删改查
insert
db.collection.insertOne({})//插入一条
db.collection.insertOne({})//插入第一条
db.collection.insertMany([{},{}])//插入多条
db.collection.insert({})//插入一条
db.collection.insert({},{})//插入第一条
db.collection.insert([{},{}])//插入多条
delete
db.collection.deleteOne({"a":1})//删除a为1的第一条
db.collection.deleteMany({"a":1})//删除a为1的全部
db.collection.deleteMany({})//清空collection
db.collection.remove()
{"a":1}//删除a为1的全部
{"a":1},{justOne:true}//删除a为1的第一条
update
db.collection.updateOne({"a":1},{$set:{"a":2}})//更新第一条
db.collection.updateOne({"a":1},{$set:{"a":2}})//更新全部
db.collection.replaceOne({"a":1},{"b":2,"c":3})//替换第一条的数据
find
db.collection.findOne({"a":1})//查询符合条件的第一条数据
db.collection.find({})//查询collection全部数据
db.collection.findOneAndDelete({"a":1})//查询正常返回第一条并且删除
db.collection.findOneAndReplace({"a":1},{"c":2,"d":3})//查询正常返回第一条并且替换
//查询正常返回第一条并更新,字段不存在就添加
db.collection.findOneAndUpdate({"d":"dd"},{$set:{"e":"ee"}})
bulk 支持以下方法,一个出错,不影响其他的
insertOne
updateOne
updateMany
replaceOne
deleteOne
deleteMany
try {
db.characters.bulkWrite(
[
{ insertOne :
{
"document" :
{
"_id" : 4, "char" : "Dithras", "class" : "barbarian", "lvl" : 4
}
}
},
{ insertOne :
{
"document" :
{
"_id" : 5, "char" : "Taeln", "class" : "fighter", "lvl" : 3
}
}
},
{ updateOne :
{
"filter" : { "char" : "Eldon" },
"update" : { $set : { "status" : "Critical Injury" } }
}
},
{ deleteOne :
{ "filter" : { "char" : "Brisbane"} }
},
{ replaceOne :
{
"filter" : { "char" : "Meldane" },
"replacement" : { "char" : "Tanys", "class" : "oracle", "lvl" : 4 }
}
}
]
);
}
catch (e) {
print(e);
}
七 索引创建
索引创建
Single Index 单键索引
db.collection.createIndex({"a":1})//a非数组 1升序索引 -1降序索引
Compound Index 复合索引
db.collection.createIndex( { "a": 1, "b": 1 } )
Multikey Index 多键值索引
db.collection.createIndex({"a":1})//这里的a是一个数组
db.collection.createIndex({"a":1,"b":1})//a数组 b非数组 创建复合索引
Text Indexes 全文索引,不支持中文
db.collection.createIndex( { "a": "text" } )
Hashed Indexes 哈希索引
db.collection.createIndex( { "_id": "hashed" } )
Unique Indexes 唯一索引
插入数据不可以重复
db.collection.createIndex( { "a": 1 }, { unique: true } )
Partial Indexes 局部索引
db.users.createIndex(//年龄>=21才能给username加升序索引,唯一索引
{ username: 1 },
{ unique: true, partialFilterExpression: { age: { $gte: 21 } } }
)
Sparse Indexes 稀疏索引
db.collection.createIndex({"a":1},{sparse:true})//对a建立索引
TTL Indexes 过期索引*重要,可做定时过期
1,只支持单个索引,复合索引不支持
2,类型要为 BSON 日期 或 含有 BSON 日期的数组
3,expireAfterSeconds 单位秒,正的 或 0 ,如果为0 在指定日期时到期
4,如果是数组,最小的那个时间到期就会删除
5,不含有该索引字段 或 字段不是日期类型,不会过期
6,_id 不能设置 TTL索引
7,时间到期后不会立马删除,后台60s执行一次
只能设置一个字段,单位秒
db.collection.createIndex({"a":1},{expireAfterSeconds:65})
八 索引管理
索引管理
//插入自定义时间
db.test.insert({'time':ISODate("2012-11-02 07:58:51")})
查看
表的全部索引
db.collection.getIndexes()
索引字段名
db.collection.getIndexKeys()
数据库全部索引
db.getCollectionNames().forEach(function(collection) {
indexes = db[collection].getIndexes();
print("Indexes for " + collection + ":");
printjson(indexes);
});
删除
删除b升序索引 -1删除降序索引
db.collection.dropIndex({"b":1})
删除全部索引
db.collection.dropIndexes()
修改
删除再创建
九 GridFS 分布式文件系统
GridFS 分布式文件系统
1,多机器储存备份
2,可以突破一般文件的限制,可以大于16M
3,分段存储,不是整个存储
mongofiles -> https://docs.mongodb.com/manual/reference/program/mongofiles/
默认localhost:27017
--host
默认27017
--port
指定数据库
--db
前缀 默认fs
--prefix
....
...
...
十 聚合管道
聚合管道 Aggregation Pipeline Stages -> https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/
db.collection.aggregate([{},{},...,{}])//一个{}表示一个管道
1,$addFields
2,$bucket
3,$bucketAuto
4,$collStats
5,$count
aggregate([//查询字段score>80的总数,假设有3条记录 返回{"passing_scores":3}
{
$match: {
score: {$gt: 80}
}
},
{
$count: "passing_scores"
}
]);
6,$facet
7,$geoNear
8,$graphLookup
9,$group
{
$group:
{
_id: null或者$字段
: { : },
...
}
}
$sum 相加
对字段price*quantity的结果相加得到总价格
totalSaleAmount: { $sum: { $multiply: [ "$price", "$quantity" ] } }
$avg 平均值
邱quantity字段平均值
averageQuantity: { $avg: "$quantity" }
$first 第一个值
$last 最后一个值
$min 最小值
$max 最大值
$push 对结果
对author分组,每个作者的标题String放入books数组
{ $group : { _id : "$author", books: { $push: "$title" } } }
aggregate( [//不分组 计算document数量
{
$group: {
_id: null,
count: { $sum: 1 }
}
}
] );
{ "_id" : null, "count" : 8 }
---
aggregate( [ { $group : { _id : "$item" } } ] );//按照item字段分组
{ "_id" : "abc" }
{ "_id" : "jkl" }
{ "_id" : "def" }
{ "_id" : "xyz" }
---
aggregate(
[
// First Stage
{
$group :
{
_id : "$item",
totalSaleAmount: { $sum: { $multiply: [ "$price", "$quantity" ] } }
}
},
// Second Stage
{
$match: { "totalSaleAmount": { $gte: 100 } }
}
]
)
//先按照item分组,对字段price*quantity的结果相加得到总价格,如果总价格>=100就显示
---
$group : {
_id : null,
totalSaleAmount: { $sum: { $multiply: [ "$price", "$quantity" ] } },
averageQuantity: { $avg: "$quantity" },
count: { $sum: 1 }
}
计算所有行的总销售额,所有行的quantity平均值,所有行的数量
10,$indexStats
11,$limit
aggregate(//取5条数据
{ $limit : 5 }
);
12,$listSessions
13,$lookup 表关联
aggregate([
{
$lookup:
{
from: "表2",
localField: "表1字段",
foreignField: "表2字段",
as: "表1添加列名,类型数组,放匹配表2的document"
}
},
{$match:{"_id":1}}//对结果再进行匹配 _id:1
]);
// localField String -> foreignField String
// localField String[] -> foreignField String
14,$match -> { $match: { } }
aggregate(
[ { $match : { author : "dave" } } ]
);
15,$merge
16,$out
aggregate([//把匹配到的结果放入diy的表中,如果已存在则自动清空内容再插入
{
$match: {score: {$gt: 80}}
},
{
$out: "diy"
}
]);
17,$planCacheStats
18,$project -> 要显示哪些字段
只显示_id title author字段
aggregate( [ { $project : { title : 1 , author : 1 } } ] )
只显示title author字段
aggregate( [ { $project : { _id: 0, title : 1 , author : 1 } } ] )
不显示lastModified字段
aggregate( [ { $project : { "lastModified": 0 } } ] )
不显示author.first lastModified字段
aggregate( [ { $project : { "author.first" : 0, "lastModified" : 0 } } ] )
不显示author字段中的first lastModified字段
aggregate( [ { $project: { "author": { "first": 0}, "lastModified" : 0 } } ] )
显示title author.first author.last
并显示字段 author.middle,值不能为"" 或 不存在字段
aggregate( [
{
$project: {
title: 1,
"author.first": 1,
"author.last" : 1,
"author.middle": {
$cond: {
if: { $eq: [ "", "$author.middle" ] },
then: "$$REMOVE",
else: "$author.middle"
}
}
}
}
] );
aggregate( [ { $project: { "stop.title": 1 } } ] )
等同于
aggregate( [ { $project: { stop: { title: 1 } } } ] )
aggregate(
[
{
$project: {
title: 1,
isbn: {
prefix: { $substr: [ "$isbn", 0, 3 ] },//下标 0 1 2
group: { $substr: [ "$isbn", 3, 2 ] },//下标 3 4
publisher: { $substr: [ "$isbn", 5, 4 ] },//下标 5 6 7 8
title: { $substr: [ "$isbn", 9, 3 ] },//下标 9 10 11
checkDigit: { $substr: [ "$isbn", 12, 1] }//下标 12
},
lastName: "$author.last",//添加新字段
copiesSold: "$copies"//添加新字段
}
}
]
)
数组 例子 { "_id" : 1, "x" : 1, "y" : 1 }
aggregate( [ { $project: { myArray: [ "$x", "$y" ] } } ] )
->{ "_id" : 1, "myArray" : [ 1, 1 ] }
原字段中无someField,显示null
aggregate( [ { $project: { myArray: [ "$x", "$y", "$someField" ] } } ] )
-> { "_id" : 1, "myArray" : [ 1, 1, null ] }
19,$redact
20,$replaceRoot
21,$replaceWith
22,$sample
23,$set
24,$skip -> { $skip: }
aggregate(// 不显示前面5条记录
{ $skip : 5 }
);
25,$sort ->{ $sort: { : , : ... } }
aggregate([// 1升序 -1降序
{ $sort : { age : 1, posts: -1 } }
])
26,$sortByCount
27,$unset
28,$unwind
十一 mapReduce
mapReduce 重量级聚合 -> mapReduce -> map -> reduce -> finalize -> out
流程图解 -> https://docs.mongodb.com/manual/core/map-reduce/
使用方法 -> https://docs.mongodb.com/manual/reference/command/mapReduce/
db.runCommand({
mapReduce: ,
map: ,
reduce: ,
finalize: ,
out: