mongodb初探

mongodb特点

  • Nosql型数据库
  • 分布式文件存储的数据库
  • C++编写,性能高
  • 采用BSON文档存储

mongodb概念

image.png
在我们本地,打开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: 抛出异常的级别
  1. 我们先新建一个数据库updateTest
> use uodateTest
switched to db uodateTest
复制代码
  1. 添加两个文档
> 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 }
>
复制代码
  1. 更改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
  1. 我们看看更改后的数据
> 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的参数:

image.png
(上图摘自菜鸟教程www.runoob.com/mongodb/mon…)

文本搜索

要执行文本搜索,则必须要有一个文本索引,每一个集合只有一个文本索引

文本索引

  1. 插入一段文档
> 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 ] }
复制代码
  1. 创建文本索引
> db.textData.createIndex({name:"text",description:"text"})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
复制代码

对name和desciption建立了text索引

  1. 文本搜索
> 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" }
复制代码

聚合

聚合操作是将选定的数据,去做一些操作,并返回这个操作的结果,常用于数据的处理

聚合管道

管道的定义是这个操作的结果可传给下一个操作
举个例子

  1. 先看看数据
> 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")
        ]
}
复制代码
  1. 执行聚合操作,找出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 }
复制代码

话不多说,这是一个很普遍的例子,直接看图

image.png
逐句解释一下

  • {$match:{status:"A"}}:筛选status = A 的文档
  • {$group:{_id:"$cust_id",total:{$sum:"$amout"}}}:group是对文档进行分组,括号内就是组的结构:_id=cust_id,total里用到了操作符group是对文档进行分组,括号内就是组的结构:\_id = cust\_id,total里用到了操作符`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

表达式操作符

常用于在聚合操作的操作符
image.png

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

复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享