1. 单机安装和启动MongoDB
# 1. 查看当前目录
lixin-macbook:bin lixin$ pwd
/Users/lixin/Developer/mongodb-cluster/mongodb-macos-x86_64-4.4.1/bin
# 2. 启动Mongod,并指定数据目录以及port
lixin-macbook:bin lixin$ ./mongod --dbpath /Users/lixin/Developer/mongodb-cluster/mongodb-macos-x86_64-4.4.1/data --port 27017
# 3. 设计启动脚本.
# #!/bin/bash
# nohup /Users/lixin/Developer/mongodb-cluster/mongodb-macos-x86_64-4.4.1/bin/mongod --dbpath /Users/lixin/Developer/mongodb-cluster/mongodb-macos-x86_64-4.4.1/data > /dev/null 2>&1 &
2. 启动MongoDB client
# 1. 查看当前目录
lixin-macbook:bin lixin$ pwd
/Users/lixin/Developer/mongodb-cluster/mongodb-macos-x86_64-4.4.1/bin
# 2. 启动客户端.
lixin-macbook:bin lixin$ ./mongo
MongoDB shell version v4.4.1
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("5721a5da-f0cc-4894-9c3f-252f07588ceb") }
MongoDB server version: 4.4.1
>
3. MongoDB常用操作
# 1.显示当前所有数据库
> show databases;
admin 0.000GB
config 0.000GB
local 0.000GB
# 2.进入到(test)数据库里(MongoDB中数据库和集合都不需要手工先创建)
> use test;
switched to db test
# 3.查看当前所在的数据库(有点类似于:db==this)
> db;
test
# 4. 查看test库下,有哪些集合
> show collections;
# 5. 删除数据库(当前所在的数据库)
> db.dropDatabase();
# 6. 删除collection
> db.users.drop();
4. MongoDB 插入文档
# 1.插入一个文档
> db.users.insert({_id:"hello",name:"hello",age:18,gender:"男"});
WriteResult({ "nInserted" : 1 })
> db.users.insert({name:"张三",age:20,gender:"男"});
WriteResult({ "nInserted" : 1 })
# 2. 插入多个文档
> db.users.insert([{name:"李四",age:21,gender:"男"},{name:"王五",age:22,gender:"女"}]);
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 2,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})
5. MongoDB 查询文档
# 1. 查询users集合下所有的文档.
> db.users.find();
{ "_id" : "hello", "name" : "hello", "age" : 18, "gender" : "男" }
{ "_id" : ObjectId("60ab58c68453d1ab4a650c01"), "name" : "张三", "age" : 20, "gender" : "男" }
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c02"), "name" : "李四", "age" : 21, "gender" : "男" }
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c03"), "name" : "王五", "age" : 22, "gender" : "女" }
# 2. 根据_id查询
> db.users.find({_id:"hello"});
{ "_id" : "hello", "name" : "hello", "age" : 18, "gender" : "男" }
# 3. WHERE name = "张三" and age = 20
> db.users.find({name:"张三",age:20});
{ "_id" : ObjectId("60ab58c68453d1ab4a650c01"), "name" : "张三", "age" : 20, "gender" : "男" }
# $lt : <
# $lte : <=
# $gt : >
# $gte : >=
# $ne : !=
# 4. WHERE age < 21
> db.users.find({age:{ $lt:21} });
{ "_id" : "hello", "name" : "hello", "age" : 18, "gender" : "男" }
{ "_id" : ObjectId("60ab58c68453d1ab4a650c01"), "name" : "张三", "age" : 20, "gender" : "男" }
# 5. WHERE age > 21
> db.users.find({age:{$gt:21}});
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c03"), "name" : "王五", "age" : 22, "gender" : "女" }
# 6. WHERE (name = "张三") OR (age < 21)
> db.users.find({ $or:[ { name:"张三" } , { age :{ $lt : 21 } } ] });
{ "_id" : "hello", "name" : "hello", "age" : 18, "gender" : "男" }
{ "_id" : ObjectId("60ab58c68453d1ab4a650c01"), "name" : "张三", "age" : 20, "gender" : "男" }
# 7. WHERE gender = "男" AND ( age > 18 OR age < 22 )
> db.users.find({ gender:"男" , $or:[ {age:{$gt:18 , $lt: 22}} ] });
{ "_id" : ObjectId("60ab58c68453d1ab4a650c01"), "name" : "张三", "age" : 20, "gender" : "男" }
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c02"), "name" : "李四", "age" : 21, "gender" : "男" }
# 8. WHERE gender = "男" AND ( age > 18 OR age < 22 ) LIMIT 1
> db.users.findOne({ gender:"男" , $or:[ {age:{$gt:18 , $lt: 22}} ] });
{
"_id" : ObjectId("60ab58c68453d1ab4a650c01"),
"name" : "张三",
"age" : 20,
"gender" : "男"
}
# 9. 统计有多少文档
> db.users.find().count();
4
# 10. 分页查询前,先查看所有的数据.
> db.users.find();
{ "_id" : ObjectId("60ab58c68453d1ab4a650c01"), "name" : "张三", "age" : 19, "gender" : "男" }
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c02"), "name" : "李四", "age" : 21, "gender" : "男" }
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c03"), "name" : "王五", "age" : 22, "gender" : "女" }
{ "_id" : ObjectId("60ab6b5e352018b15d71a152"), "name" : "赵六", "age" : 20, "gender" : "女" }
# 分页查询(每页显示两条)
> db.users.find().skip(0).limit(2);
{ "_id" : ObjectId("60ab58c68453d1ab4a650c01"), "name" : "张三", "age" : 19, "gender" : "男" }
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c02"), "name" : "李四", "age" : 21, "gender" : "男" }
# 分页查询(每页显示两条)
> db.users.find().skip(2).limit(2);
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c03"), "name" : "王五", "age" : 22, "gender" : "女" }
{ "_id" : ObjectId("60ab6b5e352018b15d71a152"), "name" : "赵六", "age" : 20, "gender" : "女" }
# 11. 按年龄的降序排序
> db.users.find();
{ "_id" : ObjectId("60ab58c68453d1ab4a650c01"), "name" : "张三", "age" : 19, "gender" : "男" }
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c02"), "name" : "李四", "age" : 21, "gender" : "男" }
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c03"), "name" : "王五", "age" : 22, "gender" : "女" }
{ "_id" : ObjectId("60ab6b5e352018b15d71a152"), "name" : "赵六", "age" : 20, "gender" : "女" }
# 年龄降序排序(1:升序 -1:降序)
> db.users.find().sort({age:-1})
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c03"), "name" : "王五", "age" : 22, "gender" : "女" }
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c02"), "name" : "李四", "age" : 21, "gender" : "男" }
{ "_id" : ObjectId("60ab6b5e352018b15d71a152"), "name" : "赵六", "age" : 20, "gender" : "女" }
{ "_id" : ObjectId("60ab58c68453d1ab4a650c01"), "name" : "张三", "age" : 19, "gender" : "男" }
# 按照age降序排序,并分页
> db.users.find().sort({age:-1}).skip(0).limit(2);
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c03"), "name" : "王五", "age" : 22, "gender" : "女" }
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c02"), "name" : "李四", "age" : 21, "gender" : "男" }
# 按照age降序排序,并分页
> db.users.find().sort({age:-1}).skip(2).limit(2);
{ "_id" : ObjectId("60ab6b5e352018b15d71a152"), "name" : "赵六", "age" : 20, "gender" : "女" }
{ "_id" : ObjectId("60ab58c68453d1ab4a650c01"), "name" : "张三", "age" : 19, "gender" : "男" }
# 12. 查询结果,仅显示:name字段.
> db.users.find({},{name:1,_id:0});
{ "_id" : ObjectId("60ab58c68453d1ab4a650c01"), "name" : "张三" }
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c02"), "name" : "李四" }
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c03"), "name" : "王五" }
{ "_id" : ObjectId("60ab6b5e352018b15d71a152"), "name" : "赵六" }
# 13. 模糊查询
# 查询name包含有:"三"的数据
> db.users.find({name:/三/});
{ "_id" : ObjectId("60ae46404ba99318ae55742a"), "name" : "张三", "age" : 20, "gender" : "男" }
# 查询name包含以:"张"开头的数据
> db.users.find({name:/^张/});
{ "_id" : ObjectId("60ae46404ba99318ae55742a"), "name" : "张三", "age" : 20, "gender" : "男" }
6. MongoDB 修改文档
注意:update默认情况下,会使用”新的对象”来替换我”旧的对象”.
如果需要的是修改文档,则需要使用”修改操作符”.
update默认情况下,只会修入一条数据(可通过参数配置multi:true),而,updateMany则可以修改多条数据.
https://docs.mongodb.com/manual/reference/method/db.collection.update/#mongodb-method-db.collection.update
# 1.根据id修改文档局部内容
> db.users.update( {"_id" : ObjectId("60ab58c68453d1ab4a650c01")} , { $set:{ age:19 } } );
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
# 2. 查询出所有数据,验证
> db.users.find();
{ "_id" : "hello", "name" : "hello", "age" : 18, "gender" : "男" }
{ "_id" : ObjectId("60ab58c68453d1ab4a650c01"), "name" : "张三", "age" : 19, "gender" : "男" }
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c02"), "name" : "李四", "age" : 21, "gender" : "男" }
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c03"), "name" : "王五", "age" : 22, "gender" : "女" }
7. MongoDB 删除文档
https://docs.mongodb.com/manual/reference/method/db.collection.remove/
# 1. 删除之前查看数据
> db.users.find();
{ "_id" : "hello", "name" : "hello", "age" : 18, "gender" : "男" }
{ "_id" : ObjectId("60ab58c68453d1ab4a650c01"), "name" : "张三", "age" : 19, "gender" : "男" }
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c02"), "name" : "李四", "age" : 21, "gender" : "男" }
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c03"), "name" : "王五", "age" : 22, "gender" : "女" }
# 2. 根据文档ID,删除文档
> db.users.remove({"_id" : "hello"});
WriteResult({ "nRemoved" : 1 })
# 3. 删除之后查看数据
> db.users.find();
{ "_id" : ObjectId("60ab58c68453d1ab4a650c01"), "name" : "张三", "age" : 19, "gender" : "男" }
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c02"), "name" : "李四", "age" : 21, "gender" : "男" }
{ "_id" : ObjectId("60ab58cb8453d1ab4a650c03"), "name" : "王五", "age" : 22, "gender" : "女" }
8. MongoDB索引
# 1. 创建新的库
> use test2;
switched to db test2
# 2.创建Collection,并批量插入20条数据
> db.orders.insert([{order_id:1,order_no:"000000001",customer_id:1,customer_name:"张三",customer_phone:"13777777771",merchant_id:8888,total_money:10.58},{order_id:2,order_no:"000000002",customer_id:2,customer_name:"李四",customer_phone:"13777777772",merchant_id:8888,total_money:11.58},{order_id:3,order_no:"000000003",customer_id:3,customer_name:"王五",customer_phone:"13777777773",merchant_id:8888,total_money:12.58},{order_id:4,order_no:"000000004",customer_id:4,customer_name:"赵六",customer_phone:"13777777774",merchant_id:8888,total_money:13.58},{order_id:5,order_no:"000000005",customer_id:5,customer_name:"小何",customer_phone:"13777777775",merchant_id:8888,total_money:14.58},{order_id:6,order_no:"000000006",customer_id:6,customer_name:"小李",customer_phone:"13777777776",merchant_id:8888,total_money:15.58},{order_id:7,order_no:"000000007",customer_id:7,customer_name:"小娜",customer_phone:"13777777777",merchant_id:8888,total_money:16.58},{order_id:8,order_no:"000000008",customer_id:8,customer_name:"小丽",customer_phone:"137777777778",merchant_id:8888,total_money:17.58},{order_id:9,order_no:"000000009",customer_id:9,customer_name:"小赵",customer_phone:"13777777779",merchant_id:8888,total_money:18.58},{order_id:10,order_no:"0000000010",customer_id:10,customer_name:"小聪",customer_phone:"13777777710",merchant_id:8888,total_money:19.58},{order_id:11,order_no:"0000000011",customer_id:1,customer_name:"张三",customer_phone:"13777777771",merchant_id:9999,total_money:22.58},{order_id:12,order_no:"0000000012",customer_id:2,customer_name:"李四",customer_phone:"13777777772",merchant_id:9999,total_money:23.58},{order_id:13,order_no:"0000000013",customer_id:3,customer_name:"王五",customer_phone:"13777777773",merchant_id:9999,total_money:24.58},{order_id:14,order_no:"0000000014",customer_id:4,customer_name:"赵六",customer_phone:"13777777774",merchant_id:9999,total_money:25.58},{order_id:15,order_no:"0000000015",customer_id:5,customer_name:"小何",customer_phone:"13777777775",merchant_id:9999,total_money:26.58},{order_id:16,order_no:"0000000016",customer_id:6,customer_name:"小李",customer_phone:"13777777776",merchant_id:9999,total_money:27.58},{order_id:17,order_no:"0000000017",customer_id:7,customer_name:"小娜",customer_phone:"13777777777",merchant_id:9999,total_money:28.58},{order_id:18,order_no:"0000000018",customer_id:8,customer_name:"小丽",customer_phone:"137777777778",merchant_id:9999,total_money:29.58},{order_id:19,order_no:"0000000019",customer_id:9,customer_name:"小赵",customer_phone:"13777777779",merchant_id:9999,total_money:30.58},{order_id:20,order_no:"0000000020",customer_id:10,customer_name:"小聪",customer_phone:"13777777710",merchant_id:9999,total_money:31.58}]);
# 3. 查看Collection(orders)中的所有索引.
> db.orders.getIndexes();
[
{
"v" : 2, # 索引引擎的版本号
"key" : { "_id" : 1 }, # 主键索引:_id升序索引
"name" : "_id_" # 索引别名
}
]
# 4. 创建索引(以租户ID升序和订单号降序,创建索引)
# 语法中Key值为你要创建的索引字段:1为指定按升序创建索引.
# 如果你想按降序来创建索引指定为:-1.
# background : 以后台方式创建索引(默认:false).
# unique : 建立的索引是否唯一(默认:false).
# name : 索引名称(可选)
# > db.orders.createIndex({order_id:-1},{background:true,unique:true});
# > db.orders.createIndex({merchant_id:1,order_id:-1},{background:true});
> db.orders.createIndex({merchant_id:1,order_no:-1},{background:true});
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
# 5. 查看Colletion(order)所有的索引
> db.orders.getIndexes();
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"v" : 2,
"key" : {
"merchant_id" : 1,
"order_no" : -1
},
"name" : "merchant_id_1_order_no_-1",
"background" : true
}
]
# 6. 按名称删除索引
> db.orders.dropIndex("merchant_id_1_order_no_-1")
{ "nIndexesWas" : 2, "ok" : 1 }
9. MongoDB 执行计划
# 1. 查看执行计划
> db.orders.find({merchant_id:8888}).explain();
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test2.orders",
"indexFilterSet" : false,
"parsedQuery" : {
"merchant_id" : {
"$eq" : 8888
}
},
"queryHash" : "0A2C21EA",
"planCacheKey" : "C7F0160F",
"winningPlan" : {
"stage" : "FETCH", # COLLSCAN:全集合扫描/FETCH:抓取
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"merchant_id" : 1,
"order_no" : -1
},
"indexName" : "merchant_id_1_order_no_-1", # 使用的索引名称
"isMultiKey" : false,
"multiKeyPaths" : {
"merchant_id" : [ ],
"order_no" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"merchant_id" : [
"[8888.0, 8888.0]"
],
"order_no" : [
"[MaxKey, MinKey]"
]
}
}
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "lixin-macbook.local",
"port" : 27017,
"version" : "4.4.1",
"gitVersion" : "ad91a93a5a31e175f5cbf8c69561e788bbc55ce1"
},
"ok" : 1
# 2. 类似MySQL索引覆盖(查询的结果集,来自于索引时,会只读取索引,无须回行读取数据行)
> db.orders.find({merchant_id:8888},{merchant_id:1,_id:0}).explain();
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test2.orders",
"indexFilterSet" : false,
"parsedQuery" : {
"merchant_id" : {
"$eq" : 8888
}
},
"queryHash" : "E87DFABE",
"planCacheKey" : "8FF1E7F9",
"winningPlan" : {
"stage" : "PROJECTION_SIMPLE",
"transformBy" : {
"merchant_id" : 1
},
"inputStage" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"merchant_id" : 1,
"order_no" : -1
},
"indexName" : "merchant_id_1_order_no_-1",
"isMultiKey" : false,
"multiKeyPaths" : {
"merchant_id" : [ ],
"order_no" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"merchant_id" : [
"[8888.0, 8888.0]"
],
"order_no" : [
"[MaxKey, MinKey]"
]
}
}
}
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "lixin-macbook.local",
"port" : 27017,
"version" : "4.4.1",
"gitVersion" : "ad91a93a5a31e175f5cbf8c69561e788bbc55ce1"
},
"ok" : 1
}
10. MongoDB聚合查询
# 常见步骤:
步骤 作用 SQL等价运算符
$match 过滤 WHERE
$project 投影 AS(别名)
$sort 排序 ORDER BY
$group 分组 GROUP BY
$skip/$limit 结果限制 SKIP/LIMIT
$lookup 左外连接 LEFT OUTER JOIN
# 案例一(显示租户所有的收入列表)
# SELECT
# merchant_id_,
# total_money_
# FROM orders
# WHERE merchant_id = 9999
# LIMIT 2,10000
# ORDER BY total_money
> db.orders.aggregate([ {$match:{merchant_id:9999}} , {$skip:2} , {$sort:{total_money:1}} , {$project:{ merchant_id_:"$merchant_id" , total_money_:"$total_money" }} ]);
# 案例二(统计租户订单数量大于2笔的记录)
# SELECT
# merchant_id AS _id,
# COUNT(*) AS merchant_cnt
# FROM orders
# GROUP BY merchant_id
# HAVING COUNT(*) > 2
> db.orders.aggregate([ { $group:{_id:"$merchant_id",merchant_cnt:{ $sum: 1 }} } , { $match:{merchant_cnt: { $gt : 2 }} } ]);
# 案例三(统计租户所有的收入总计)
# SELECT
# merchant_id AS _id,
# SUM(total_money) AS total
# FROM orders
# GROUP BY merchant_id
# ORDER BY _id
> db.orders.aggregate([ { $group:{_id:"$merchant_id" , total:{ $sum:"$total_money" } } } ,{ $sort : { _id : -1 } } ] );