mongodb特点
- Nosql型数据库
- 分布式文件存储的数据库
- C++编写,性能高
- 采用
BSON
文档存储
mongodb概念
在我们本地,打开mongodb安装目录下的bin/mongodb.exe
,出现了mongodb的终端,我们在终端输入命令
数据库
添加/切换数据库
> use "mongodbTest"
复制代码
输出:
> switched to db mongodbTest
复制代码
当没有这个monodbTest数据库时,mongodb会自动创建这一个数据库
展示所有的mongodb数据库
show dbs
复制代码
删除数据库
>use mongodbTest
> db.dropDatabase();
复制代码
先切换到当前要删除的数据库,再去删除
输出:
{ "dropped" : "mongodbTest", "ok" : 1 }
复制代码
集合(表)
创建集合(表)
> db.createCollection("colle");
{ "ok" : 1 }
复制代码
通用表达式:
> db.createCollection(name, options)
复制代码
创建封顶集合(表)
封顶集合指的是固定大小的集合,当它的空间被占满之后,就覆盖掉最早存入的数据
为什么要使用封顶集合呢?
更高的性能
更高的吞吐量
由于是固定大小,插入的顺序得到了保证,因此历史查询不需要索引排序,没有这种索引开销,封顶集合有更高的吞吐量
> db.createCollection("cappedSize",{size:6142800,max:10000,capped:true})
{ "ok" : 1 }
复制代码
解释一下上面的例子:
cappedSize
: 集合名字size
:集合的固定大小,字节为单位,这个例子中是6142800B,若是超过了这个大小,那么mongodb将会把较早之前的数据覆盖掉max
:集合最大可容纳的文档数为10000个capped
:是否为封顶数组,默认为false
查看集合(表)
> show collections
colle
复制代码
在mongodb中,你不需要特意创建集合,当你将一个不存在的集合插入数据的时候,这个集合就会被mongodb默认创建了
查看集合中的文档
db.collecName.find(<query>)
复制代码
<query>
是查询条件
不传query的话,默认查询该集合的全部文档
> db.collecName.find()
{ "_id" : ObjectId("607ce52e81fa2aa6bc3cf6a1"), "item" : "notebook", "qty" : 50, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "P" }
{ "_id" : ObjectId("607ce52e81fa2aa6bc3cf6a3"), "item" : "planner", "qty" : 75, "size" : { "h" : 22.85, "w" : 30, "uom" : "cm" }, "status" : "D" }
复制代码
以上查询等同于SQL语句SELECT * FROM inventory
传query的例子:
> db.inventory.find({status:"D"})
{ "_id" : ObjectId("607ce52e81fa2aa6bc3cf6a3"), "item" : "planner", "qty" : 75, "size" : { "h" : 22.85, "w" : 30, "uom" : "cm" }, "status" : "D" }
复制代码
以上查询等同于SQL语句SELECT * FROM inventory WHERE status = "D"
加上查询操作符的例子:
> db.inventory.find({status:{$in:["A","D"]}})
{ "_id" : ObjectId("607cecfdb180136a61da3a64"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "status" : "A" }
{ "_id" : ObjectId("607cecfdb180136a61da3a65"), "item" : "notebook", "qty" : 50, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "A" }
{ "_id" : ObjectId("607cecfdb180136a61da3a66"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "D" }
{ "_id" : ObjectId("607cecfdb180136a61da3a67"), "item" : "planner", "qty" : 75, "size" : { "h" : 22.85, "w" : 30, "uom" : "cm" }, "status" : "D" }
{ "_id" : ObjectId("607cecfdb180136a61da3a68"), "item" : "postcard", "qty" : 45, "size" : { "h" : 10, "w" : 15.25, "uom" : "cm" }, "status" : "A" }
复制代码
使用Llmit
db.collectionName.find().limit(NUMBER)
用于读取指定的文档,NUMBER是数字
> db.orders.find()
{ "_id" : ObjectId("607e4620b180136a61da3a6e"), "cust_id" : "A123", "amount" : 500, "status" : "A" }
{ "_id" : ObjectId("607e4620b180136a61da3a6f"), "cust_id" : "A123", "amount" : 250, "status" : "A" }
{ "_id" : ObjectId("607e4620b180136a61da3a70"), "cust_id" : "B212", "amount" : 200, "status" : "A" }
{ "_id" : ObjectId("607e4620b180136a61da3a71"), "cust_id" : "A123", "amount" : 300, "status" : "D" }
> db.orders.find().limit(2)
{ "_id" : ObjectId("607e4620b180136a61da3a6e"), "cust_id" : "A123", "amount" : 500, "status" : "A" }
{ "_id" : ObjectId("607e4620b180136a61da3a6f"), "cust_id" : "A123", "amount" : 250, "status" : "A" }
复制代码
limit(2)
:筛选出这个集合中的前两个数据
使用Skip
db.collectionName.find().skip(NUMBER)
用于跳过指定的文档读取
> db.orders.find()
{ "_id" : ObjectId("607e4620b180136a61da3a6e"), "cust_id" : "A123", "amount" : 500, "status" : "A" }
{ "_id" : ObjectId("607e4620b180136a61da3a6f"), "cust_id" : "A123", "amount" : 250, "status" : "A" }
{ "_id" : ObjectId("607e4620b180136a61da3a70"), "cust_id" : "B212", "amount" : 200, "status" : "A" }
{ "_id" : ObjectId("607e4620b180136a61da3a71"), "cust_id" : "A123", "amount" : 300, "status" : "D" }
> db.orders.find().skip(1)
{ "_id" : ObjectId("607e4620b180136a61da3a6f"), "cust_id" : "A123", "amount" : 250, "status" : "A" }
{ "_id" : ObjectId("607e4620b180136a61da3a70"), "cust_id" : "B212", "amount" : 200, "status" : "A" }
{ "_id" : ObjectId("607e4620b180136a61da3a71"), "cust_id" : "A123", "amount" : 300, "status" : "D" }
复制代码
从上面的例子我们可以看到,我们使用skip(1)跳过了第一条文档
sort排序查看集合
sort({KEY:n})
,按照KEY的值进行排序
n=1
升序n=-1
降序
> db.orders.find()
{ "_id" : ObjectId("607e4620b180136a61da3a6e"), "cust_id" : "A123", "amount" : 500, "status" : "A" }
{ "_id" : ObjectId("607e4620b180136a61da3a6f"), "cust_id" : "A123", "amount" : 250, "status" : "A" }
{ "_id" : ObjectId("607e4620b180136a61da3a70"), "cust_id" : "B212", "amount" : 200, "status" : "A" }
{ "_id" : ObjectId("607e4620b180136a61da3a71"), "cust_id" : "A123", "amount" : 300, "status" : "D" }
> db.orders.find().sort({"amount":1})
{ "_id" : ObjectId("607e4620b180136a61da3a70"), "cust_id" : "B212", "amount" : 200, "status" : "A" }
{ "_id" : ObjectId("607e4620b180136a61da3a6f"), "cust_id" : "A123", "amount" : 250, "status" : "A" }
{ "_id" : ObjectId("607e4620b180136a61da3a71"), "cust_id" : "A123", "amount" : 300, "status" : "D" }
{ "_id" : ObjectId("607e4620b180136a61da3a6e"), "cust_id" : "A123", "amount" : 500, "status" : "A" }
复制代码
db.orders.find().sort({"amount":1})
我们对amount的值进行一个升序
排序
更多例子,参考:docs.mongoing.com/mongodb-cru…
删除集合(表)
> db.colle.drop();
复制代码
删除掉为:colle
的集合
集合中插入文档(行)
insert
—插入单条或多条数据,不建议采用
> db.mongodbColleTest.insert({name:"arzhu"})
复制代码
为mongodbColleTest
集合插入数据。
如果不存在这个mongodbColleTest集合,mongodb就会去创建它
insertOne
—插入单条数据,返回插入的数据
> var doucument = {title:"doc",desc:"新加的数据"};
> db.mongodbColleTest.insertOne(doucument)
复制代码
insertMany()
—插入多条数据,返回被插入的数据集合
> const res = db.tableCopy.insertMany([{name:"1"},{name:2}])
> res
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("60790594eaf92c106aba6674"),
ObjectId("60790594eaf92c106aba6675")
]
}
复制代码
插入单条数据,使用insertOne(),插入多条数据使用insertMany()
更新文档(行)
在mongodb中我们使用update
去更新所需的数据
db.collectionsName.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
复制代码
- upsert: 如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
- multi: mongodb默认只找到第一个符合query的文档,更改这个配置可对所有符合query的文档进行更新
- writeConcern: 抛出异常的级别
- 我们先新建一个数据库
updateTest
> use uodateTest
switched to db uodateTest
复制代码
- 添加两个文档
> db.updateTest.insertMany([{name:"arzhu",value:1},{name:"arzhu",value:2}])
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("60794a012582410d8e7d8170"),
ObjectId("60794a012582410d8e7d8171")
]
}
> db.updateTest.find()
{ "_id" : ObjectId("60794a012582410d8e7d8170"), "name" : "arzhu", "value" : 1 }
{ "_id" : ObjectId("60794a012582410d8e7d8171"), "name" : "arzhu", "value" : 2 }
>
复制代码
- 更改
name=arzhu
的文档
> db.updateTest.update({name:"arzhu"},{$set:{value:"newValue"}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
复制代码
这里我们看一下update的参数update({name:"arzhu"},{$set:{value:"newValue"}})
{name:"arzhu"}
选择了name=”arzhu”的文档我们没有更改multi参数,这个参数默认为false,这也就是说,我们更改的name=’arzhu’的文档只是更改匹配的第一条文档,其他文档没被更改{$set:{value:"newValue"}}
使用了$set去更改匹配{name:"arzhu"}
的文档,将value的值更改成了newValue
- 我们看看更改后的数据
> db.updateTest.find()
{ "_id" : ObjectId("60794a012582410d8e7d8170"), "name" : "arzhu", "value" : "newValue" }
{ "_id" : ObjectId("60794a012582410d8e7d8171"), "name" : "arzhu", "value" : 2 }
>
复制代码
可以看到只有第一条文档被更改了
5. 更改multi的值,尝试更改所有匹配name=arzhu
的文档
> db.updateTest.update({name:"arzhu"},{$set:{value:"3"}},{multi:true});
WriteResult({ "nMatched" : 2, "nUpserted" : 0, "nModified" : 2 })
> db.updateTest.find()
{ "_id" : ObjectId("60794a012582410d8e7d8170"), "name" : "arzhu", "value" : "3" }
{ "_id" : ObjectId("60794a012582410d8e7d8171"), "name" : "arzhu", "value" : "3" }
复制代码
删除文档(行)
deleteMany()
用于删除多个文档(行)
db.collectionName.deleteMany(<query>)
复制代码
deleteOne()
用于删除单个符合的文档
deleteMany()
先看看deleteMany()
要想删除某个集合中的所有数据,可传入一个空的数据:{}
> db.updateTest.find()
{ "_id" : ObjectId("60795fa92582410d8e7d8173"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "status" : "A" }
{ "_id" : ObjectId("60795fa92582410d8e7d8174"), "item" : "notebook", "qty" : 50, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "P" }
{ "_id" : ObjectId("60795fa92582410d8e7d8175"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "D" }
{ "_id" : ObjectId("60795fa92582410d8e7d8176"), "item" : "planner", "qty" : 75, "size" : { "h" : 22.85, "w" : 30, "uom" : "cm" }, "status" : "D" }
{ "_id" : ObjectId("60795fa92582410d8e7d8177"), "item" : "postcard", "qty" : 45, "size" : { "h" : 10, "w" : 15.25, "uom" : "cm" }, "status" : "A" }
> db.updateTest.deleteMany({})
{ "acknowledged" : true, "deletedCount" : 5 }
>
复制代码
要是想删除某个文档,直接添加对应的匹配条件:
> db.inventory.deleteMany({status:"A"})
{ "acknowledged" : true, "deletedCount" : 2 }
复制代码
deleteOne()
仅用于删除符合条件的第一个文档
> db.inventory.deleteOne({status:"D"})
{ "acknowledged" : true, "deletedCount" : 1 }
> db.inventory.find()
{ "_id" : ObjectId("607ce52e81fa2aa6bc3cf6a1"), "item" : "notebook", "qty" : 50, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "P" }
{ "_id" : ObjectId("607ce52e81fa2aa6bc3cf6a3"), "item" : "planner", "qty" : 75, "size" : { "h" : 22.85, "w" : 30, "uom" : "cm" }, "status" : "D" }
复制代码
索引
索引是什么?可以理解为对某些文档的标识
索引的作用
减少查询的文档的数量,提高查询效率,要是没有索引.就会去查询集合的所有文档,效率太低
创建索引
db.collectionName.createIndex({KEY:n},{options})
复制代码
KEY
:要索引的键n
:n=1
按照升序创建索引,n=-1
按照降序创造索引,n=其他KEY
创造了一个有名索引
options的参数:
(上图摘自菜鸟教程www.runoob.com/mongodb/mon…)
文本搜索
要执行文本搜索,则必须要有一个文本索引
,每一个集合只有一个文本索引
文本索引
- 插入一段文档
> db.textData.insertMany(
[
{ _id: 1, name: "Java Hut", description: "Coffee and cakes" },
{ _id: 2, name: "Burger Buns", description: "Gourmet hamburgers" },
{ _id: 3, name: "Coffee Shop", description: "Just coffee" },
{ _id: 4, name: "Clothes Clothes Clothes", description: "Discount clothing" },
{ _id: 5, name: "Java Shopping", description: "Indonesian goods" }
]
)
{ "acknowledged" : true, "insertedIds" : [ 1, 2, 3, 4, 5 ] }
复制代码
- 创建文本索引
> db.textData.createIndex({name:"text",description:"text"})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
复制代码
对name和desciption建立了text索引
- 文本搜索
> db.textData.find({$text:{$search:"java coffee shop"}})
{ "_id" : 3, "name" : "Coffee Shop", "description" : "Just coffee" }
{ "_id" : 1, "name" : "Java Hut", "description" : "Coffee and cakes" }
{ "_id" : 5, "name" : "Java Shopping", "description" : "Indonesian goods" }
复制代码
分析一下这段代码的意思
$text
筛选有文档索引的文档$search:'java coffee shop'
:对’java’,’coffee’,’shop’字段进行查询,当有文本索引的文档存在这些字段时,就会被索引出来.
注意这里的文本搜索时不区分大小写的
更多例子:
- 查询带有
"just coffee"
字段的文档
> db.textData.find({$text:{$search:"\"just coffee\""}})
{ "_id" : 3, "name" : "Coffee Shop", "description" : "Just coffee" }
复制代码
- 查询包含了”java”但不包含”hut”的文档
-
排除
> db.textData.find({$text:{$search:"java -hut"}})
{ "_id" : 5, "name" : "Java Shopping", "description" : "Indonesian goods" }
复制代码
聚合
聚合操作是将选定的数据,去做一些操作,并返回这个操作的结果
,常用于数据的处理
聚合管道
管道的定义是这个操作的结果可传给下一个操作
举个例子
- 先看看数据
> db.orders.insertMany([
... {
... cust_id:"A123",
... amount:500,
... status:"A"
... },
... {
... cust_id:"A123",
... amount:250,
... status:"A"
... },
... {
... cust_id:"B212",
... amount:200,
... status:"A"
... },
... {
... cust_id:"A123",
... amount:300,
... status:"D"
... },
... ]);
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("607e4620b180136a61da3a6e"),
ObjectId("607e4620b180136a61da3a6f"),
ObjectId("607e4620b180136a61da3a70"),
ObjectId("607e4620b180136a61da3a71")
]
}
复制代码
- 执行聚合操作,找出
status="A"的数据的和,以cuse_id为键进行分组
> const res = db.orders.aggregate([{$match:{status:"A"}},{$group:{_id:"$cust_id",total:{$sum:"$amount"}}}])
> res
{ "_id" : "A123", "total" : 750 }
{ "_id" : "B212", "total" : 200 }
复制代码
话不多说,这是一个很普遍的例子,直接看图
逐句解释一下
{$match:{status:"A"}}
:筛选status = A 的文档{$group:{_id:"$cust_id",total:{$sum:"$amout"}}}
:sum`代表的意思是,计算amout的和
操作符
管道操作符
$match
:筛选出符合条件的文档.如{$match:{status:"A"}}
就代表筛选出status=A的文档数据$project
:修改文档结构,命名,删除,增加等- “
查询操作符
$in
:包含此条件.如{status:{$in:["A","D"]}}
status的值等于A或D的文档$or
:
修改操作符
$set
:对此值进行修改.如{$set:{value:"newValue"}}
对value进行修改,修改成newValue这个值
比较运算符
$gt
: 大于某个值,如age:{$gt:70},age大于70$gte
: 大于等于某个值,如age:{$gte:70},age大于或等于70$lt
: 小于某个值,如age:{$lt:40},age小于40$lte
: 小于等于某个值,如age:{$lte:90},age小于等于90
表达式操作符
常用于在聚合操作的操作符
Node连接Mongodb
参考:docs.mongodb.com/drivers/nod…
创建连接
const {MongoClient} = require("mongodb");
const url = "mongodb://localhost:27017"; //mongodb默认是27017端口
const dbName = "updateTest"; // 连接updateTest数据库
const client = new MongoClient(url,{useUnifiedTopology:true}); //新建一个连接
client.connect((err)=>{
if(err){
console.log(err);
return;
}
console.log("链接成功");
const db = client.db(dbName);
})
复制代码
查找数据
const {MongoClient} = require("mongodb");
const url = "mongodb://localhost:27017"; //mongodb默认是27017端口
const dbName = "updateTest";
const client = new MongoClient(url,{useUnifiedTopology:true});
client.connect((err)=>{
if(err){
console.log(err);
return;
}
console.log("链接成功");
const db = client.db(dbName);
db.collection("inventory").find({}).toArray((err,data)=>{ //查找 updateTest 下的 inventory表
if(err){
console.log(err);
return;
}
console.log(data);
client.close(); //关闭此次连接
})
})
复制代码
插入数据
const {MongoClient} = require("mongodb");
const url = "mongodb://localhost:27017"; //mongodb默认是27017端口
const dbName = "updateTest";
const client = new MongoClient(url,{useUnifiedTopology:true});
client.connect((err)=>{
if(err){
console.log(err);
return;
}
console.log("链接成功");
const db = client.db(dbName);
// 在inventory表上插入数据
db.collection("inventory").insertOne({ "item" : "arzhu", "qty" : 1, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }},(err,res)=>{
if(err){
console.log(err);
return;
}
console.log("看看结果:",res);
})
})
复制代码
删除数据
const {MongoClient} = require("mongodb");
const url = "mongodb://localhost:27017"; //mongodb默认是27017端口
const dbName = "updateTest";
const client = new MongoClient(url,{useUnifiedTopology:true});
client.connect((err)=>{
if(err){
console.log(err);
return;
}
console.log("链接成功");
const db = client.db(dbName);
db.collection("inventory").deleteMany({item:"arzhu"},(err,res)=>{ //删除item="arzhu"的数据
if(err){
console.log(err);
return;
}
console.log("看看结果:",res);
})
})
复制代码
修改数据
const {MongoClient} = require("mongodb");
const url = "mongodb://localhost:27017"; //mongodb默认是27017端口
const dbName = "updateTest";
const client = new MongoClient(url,{useUnifiedTopology:true});
client.connect((err)=>{
if(err){
console.log(err);
return;
}
console.log("链接成功");
const db = client.db(dbName);
//修改inventory表中item=journal的第一个匹配到的数据,使用$set操作符设置qty=29 要更改多个数据,请使用updateMany
db.collection("inventory").updateOne({item:"journal"},{$set:{qty:29}},(err,res)=>{
if(err){
console.log(err);
return;
}
console.log("看看结果:",res);
client.close();
})
})
复制代码