MongoDB——基础操作

Posted 小王子jvm

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MongoDB——基础操作相关的知识,希望对你有一定的参考价值。

MongoDB基本介绍

传统的关系型数据库(如mysql),在数据操作的“三高”需求以及应对Web2.0的网站需求面前,显得力不从心。 解释:“三高”需求:

  • High performance - 对数据库高并发读写的需求。
  • Huge Storage - 对海量数据的高效率存储和访问的需求。
  • High Scalability && High Availability- 对数据库的高可扩展性和高可用性的需求。

而MongoDB可应对“三高”需求。

具体的应用场景如:

  1. 社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。
  2. 游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、高效率存储和访问。
  3. 物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。
  4. 物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析。
  5. 视频直播,使用 MongoDB 存储用户信息、点赞互动信息等。

这些应用场景中,数据操作方面的共同特点是: 数据量大 、写入操作频繁(读写都很频繁)、价值较低的数据,对事务性要求不高对于这样的数据,我们更适合使用MongoDB来实现数据的存储。

所以什么是MongoDB?

MongoDB是一个开源、高性能、无模式的文档型数据库,当初的设计就是用于简化开发和方便扩展,是NoSQL数据库产品中的一种。是最 像关系型数据库(MySQL)的非关系型数据库。

它支持的数据结构非常松散,是一种类似于 JSON 的 格式叫BSON,所以它既可以存储比较复杂的数据类型,又相当的灵活。

MongoDB中的记录是一个文档,它是一个由字段和值对(field:value)组成的数据结构。MongoDB文档类似于JSON对象,即一个文档认为就是一个对象。字段的数据类型是字符型,它的值除了使用基本的一些类型外,还可以包括其他文档、普通数组和文档数组。

什么东西都是这样,类比一下,一下子就清晰了很多:

SQL术语/概念MongoDB术语/概念解释/说明
databasedatabase数据库
tablecollection数据库表/集合
rowdocument数据行/文档
columnfiled数据库字段/域
indexindex索引
table joins表连接,MongoDB不支持
嵌入文档MongoDB通过嵌入式文档来替代多表连接
primary keyprimary key主键/MongoDB自动将_id字段设置为主键

数据类型

MongoDB的最小存储单位就是文档(document)对象。文档(document)对象对应于关系型数据库的行。数据在MongoDB中以 BSON(Binary-JSON)文档的格式存储在磁盘上。

BSON(Binary Serialized Document Format)是一种类似json的一种二进制形式的存储格式,简称Binary JSON。BSON和JSON一样,支持内嵌的文档对象和数组对象,但是BSON有JSON没有的一些数据类型,如Date和BinData类型。

BSON采用了类似于 C 语言结构体的名称、对表示方法,支持内嵌的文档对象和数组对象,具有轻量性、可遍历性、高效性的三个特点,可以有效描述非结构化数据和结构化数据。这种格式的优点是灵活性高,但它的缺点是空间利用率不是很理想。

单机部署(安装流程)

Windows安装

下载安装包

MongoDB 提供了可用于 32 位和 64 位系统的预编译二进制包,你可以从MongoDB官网下载安装,MongoDB 预编译二进制包下载地址: https://www.mongodb.com/download-center#community

下载zip压缩包,然后解压到一个文件夹中,在解压目录中自己手动简历一个文件夹用来放数据:例如:data/db

启动方式:

  • 在 bin 目录中打开命令行提示符,输入如下命令:mongod --dbpath=..\\data\\db

在启动信息中可以看到,mongoDB的默认端口是27017,如果我们想改变默认的启动端口,可以通过–port来指定端口。 为了方便我们每次启动,可以将安装目录的bin目录设置到环境变量的path中, bin 目录下是一些常用命令,比如 mongod 启动服务用的, mongo 客户端连接服务用的。

  • 配置文件方式启动服务

在解压目录中新建 config 文件夹,该文件夹中新建配置文件 mongod.conf ,内如参考如下:

storage:
    #指定数据文件位置,也就是上面创建的文件夹
    dbPath: D:\\学习资源\\mongodb\\mongodb-win32-x86_64-windows-4.4.6\\data\\db

详细配置项内容可以参考官方文档:https://docs.mongodb.com/manual/reference/configuration-options/

[ PS ]:配置文件中如果使用双引号,比如路径地址,自动会将双引号的内容转义。如果不转义,则会报错:

启动方式:mongod -f ../config/mongod.confmongod --config ../config/mongod.conf

其他配置参考:

systemLog:
    destination: file
    #生成的日志文件放在那个位置
    path: "D:/mongodb-win32-x86_64-2008plus-ssl-4.0.1/log/mongod.log"
    #产生的日志以追加的方式添加
    logAppend: true
storage:	
    journal:
    	enabled: true
    #数据文件
	dbPath: "D:/mongodb-win32-x86_64-2008plus-ssl-4.0.1/data"
net:
    #bindIp: 127.0.0.1
    port: 27017
setParameter:
	# 
    enableLocalhostAuthBypass: false

Shell连接(mongo命令)

在命令提示符输入以下shell命令即可完成登陆 mongomongo --host=127.0.0.1 --port=27017

查看已经有的数据库 : >show databases(其实这个数据库和MySQL有点像,只不过MySQL存储数据是拆散,这个是一个文档也就是完整的存储,然后二者的语法使用不同罢了)

退出:exit

Compass-图形化界面客户端

到MongoDB官网下载MongoDB Compass 地址:https://www.mongodb.com/try/download/compass

如果是下载安装版,则按照步骤安装;如果是下载加压缩版,直接解压,执行里面的 MongoDBCompassCommunity.exe 文件即可。 在打开的界面中,输入主机地址、端口等相关信息,点击连接:然后输入对应的IP和端口即可。

Linux系统安装

其实和Windows差不多也是这几个操作,步骤如下:(有点坑最好使用docker部署)

  1. 下载对应的安装包:mongod-linux-x86_64-4.0.10.tgz 。

  2. 上传压缩包到Linux中,解压到当前目录:tar -xvf mongodb-linux-x86_64-4.0.10.tgz

  3. 移动解压后的文件夹到指定的目录中:mv mongodb-linux-x86_64-4.0.10 /usr/local/mongodb

  4. 新建几个目录,分别用来存储数据和日志:

    #数据存储目录
    mkdir -p /mongodb/single/data/db
    #日志存储目录
    mkdir -p /mongodb/single/log
    
  5. 新建并修改配置文件:vi /mongodb/single/mongod.conf

    配置文件的内容如下:

    systemLog:
        #MongoDB发送所有日志输出的目标指定为文件
        destination: file
        #mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
        path: "/mongodb/single/log/mongod.log"
        #当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。
        logAppend: true
    storage:
        #mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod。
        dbPath: "/mongodb/single/data/db"
        journal:
        #启用或禁用持久性日志以确保数据文件保持有效和可恢复。
        	enabled: true
    processManagement:
        #启用在后台运行mongos或mongod进程的守护进程模式。
        fork: true
    net:
        #服务实例绑定的IP,默认是localhost
        bindIp: localhost,192.168.0.2
        #绑定的端口,默认是27017
        port: 27017
    

    注意格式是yaml格式!!!

  6. 启动MongoDB服务: /usr/local/mongodb/bin/mongod -f /mongodb/single/mongod.conf

如果出错了,自行百度吧,不多不说21世纪了,用docker还是最舒服的。

docker安装方式

首先拉去镜像:docker pull mongo

然后启动容器运行这个镜像:docker run --name mongodb -p 27017:27017 -d mongo:latest

上面两种安装方式,如果有数据损坏,则需要进行如下操作(了解):

  1. 删除lock文件:rm -f /mongodb/single/data/db/*.lock
  2. 修复数据:./mongod --repair --dbpath=/mongodb/single/data/db

常用命令大全

基本案例

存放文章评论的数据存放到MongoDB中,数据结构参考如下:

数据库:articledb

数据库相关操作

  • 选择和创建数据库:use DBName,如果这个数据库不存在会自动的创建。所以创建也是这个命令。

  • 查看有权限查看的数据库:show dbs或者show databases

  • 查看当前使用的数据库:db

    MongoDB 中默认的数据库为 test,如果你没有选择数据库,集合将存放在 test 数据库中。

  • 删除数据库:db.dropDatabase(),主要用来删除已经持久化的数据库

有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。

  • admin:保存的就是用户的基本信息以及对应的一个权限
  • local: 用来存储限于本地单台服务器的任意集合
  • config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。

集合相关操作

集合,类似关系型数据库中的表。 可以显示的创建,也可以隐式的创建

  • 集合的创建db.createCollection(name),这个name就是创建的集合名字。

    例如:创建一个sheep,db.createCollection(“sheep”).

  • 查看当前数据库的集合:show collections 或者 show tables(好家伙,直接和MySQL一样)

  • 集合的删除:db.collection.drop()【删除所有集合】 或者 db.集合名字.drop()【删除指定集合】

    如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。

    例如删除上面创建的这个集合:db.mycollection.drop()

当向一个集合中插入一个文档的时候,如果集合不存在,则会自动创建集合。

文档操作(CRUD)

文档(document)的数据结构和 JSON 基本一样。 所有存储在集合中的数据都是 BSON 格式

文档插入

  • 单个插入,使用insert() 或 save() 方法向集合中插入文档,语法如下:
db.collection.insert(
    
        json数据格式即可
    
)
# 例如:
db.comment.insert(
    
        "articleid":"100000",
        "content":"今天天气真好,阳光明媚",
        "userid":"1001",
        "nickname":"Rose",
        "createdatetime":new Date(),
        "likenum":NumberInt(10),
        "state":null
    
)
# 说明:
1)comment集合如果不存在,则会隐式创建
2)mongo中的数字,默认情况下是double类型,如果要存整型,必须使用函数NumberInt(整型数字),否则取出来就有问题了。
3)插入当前日期使用 new Date()
4)插入的数据没有指定 _id ,会自动生成主键值
5)如果某字段没值,可以赋值为null,或不写该字段。

如果执行之后返回:WriteResult( "nInserted" : 1 )代表插入成功。

  1. 文档中的键/值对是有序的。
  2. 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。
  3. MongoDB区分类型和大小写。
  4. MongoDB的文档不能有重复的键。
  5. 文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。

文档键命名规范:

  1. 键不能含有\\0 (空字符)。这个字符用来表示键的结尾。
  2. .和$有特别的意义,只有在特定环境下才能使用。
  3. 以下划线"_"开头的键是保留的(不是严格要求的)。
  • 批量插入,没什么好说的,就是多个json数据而已
db.comment.insert(
    
        "_id":"1",
        "articleid":"100000",
        "content":"今天天气真好,阳光明媚",
        "userid":"1001",
        "nickname":"Rose",
        "createdatetime":new Date(),
        "likenum":NumberInt(10),
        "state":null
    ,
    
        "_id":"2",
        "articleid":"100001",
        "content":"今天天气真好,阳光明媚",
        "userid":"1002",
        "nickname":"Lisi",
        "createdatetime":new Date(),
        "likenum":NumberInt(32),
        "state":null
    
)

插入时指定了 _id ,则主键就是该值。 如果某条数据插入失败,将会终止插入,但已经插入成功的数据不会回滚掉。 因为批量插入由于数据较多容易出现失败,因此,可以使用try catch进行异常捕捉处理,测试的时候可以不处理。如(了解):

try 
    db.comment.insertMany(
        [
            "_id":"1",
            "articleid":"100000",
            "content":"今天天气真好,阳光明媚",
            "userid":"1001",
            "nickname":"Rose",
            "createdatetime":new Date(),
            "likenum":NumberInt(10),
            "state":null
        ,
        
            "_id":"2",
            "articleid":"100001",
            "content":"今天天气真好,阳光明媚",
            "userid":"1002",
            "nickname":"Lisi",
            "createdatetime":new Date(),
            "likenum":NumberInt(32),
            "state":null
        ]
	)
 catch(e)
    print(e)

查询数据的语法格式如下:

db.collection.find(<query>, [projection])

  • query:可选。使用查询运算符指定选择筛选器。若要返回集合中的所有文档,请省略此参数或传递空文档 ( )。

  • projection : 可选。指定要在与查询筛选器匹配的文档中返回的字段(投影)。若要返回匹配文档中的所有字段, 请省略此参数。

比如查询所有:db.comment.find()db.comment.find()

这里你会发现每条文档会有一个叫_id的字段,这个相当于我们原来关系数据库中表的主键,当你在插入文档记录时没有指定该字段,MongoDB会自动创建,其类型是ObjectID类型。 如果我们在插入文档记录时指定该字段也可以,其类型可以是ObjectID类型,也可以是MongoDB支持的任意类型。

  • 按一定条件来查询

比如我想查询userid为1003的记录,怎么办?很简单!只 要在find()中添加参数即可,参数也是json格式,如:db.comment.find(userid:'1003')

如果你只需要返回符合条件的第一条数据,我们可以使用findOne命令来实现,语法和find一样。 如:查询用户编号是1003的记录,但只最多返回符合条件的第一条记录:db.comment.findOne(userid:'1003')

  • 投影查询(Projection Query):

如果要查询结果返回部分字段,则需要使用投影查询(不显示所有字段,只显示指定的字段)。

如:查询结果只显示 _id、userid、nickname :(1表示显示,0表示不显示)

> db.comment.find(userid:"1003",userid:1,nickname:1)
 "_id" : "4", "userid" : "1003", "nickname" : "凯撒" 
 "_id" : "5", "userid" : "1003", "nickname" : "凯撒" 

默认 _id 会显示。如:查询结果只显示 、userid、nickname ,不显示 _id :

> db.comment.find(userid:"1003",userid:1,nickname:1,_id:0)
 "userid" : "1003", "nickname" : "凯撒" 
 "userid" : "1003", "nickname" : "凯撒" 

文档的更新

更新文档的语法:

db.collection.update(query, update, options)
//或
db.collection.update(
    <query>,	//查找想更新的数据
    <update>,	//更新后的数据
    
    //下面这都是可选项,代表一些更新的特性
    
        upsert: <boolean>,
        multi: <boolean>,
        writeConcern: <document>,
        collation: <document>,
        arrayFilters: [ <filterdocument1>, ... ],
        hint: <document|string> // Available starting in MongoDB 4.2
    
)

例如:我们想修改_id为1的记录,点赞量为1001,输入以下语句:

db.comment.update(_id:"1",likenum:NumberInt(1001))

执行后,我们会发现,这条文档除了likenum字段其它字段都不见了,由于没有指定其他字段,默认删除了。

如果想要局部修改,们需要使用修改器$set来实现,命令如下:(修改_id为2的记录,浏览量为889)

db.comment.update(_id:"2",$set:likenum:NumberInt(889))

批量修改:

//默认只修改第一条数据
db.comment.update(userid:"1003",$set:nickname:"凯撒2")
//修改所有符合条件的数据,如果不加后面的参数,则只更新符合条件的第一条记录
db.comment.update(userid:"1003",$set:nickname:"凯撒大帝",multi:true)

列值增长的修改,实现对某列值在原有值的基础上进行增加或减少,可以使用 $inc 运算符来实现。

//对3号数据的点赞数,每次递增1
db.comment.update(_id:"3",$inc:likenum:NumberInt(1))

文档删除

删除文档的语法结构:db.集合名称.remove(条件)

以下语句可以将数据全部删除,请慎用:db.集合名称.remove()

如果删除指定条件的例如:db.comment.remove(_id;"1")

高级的查询

统计查询

统计查询使用count()方法,语法如下:db.collection.count(query, options)

例如:统计所有记录数量:db.comment.count()

再如:按条件统计记录数(统计userid为1003的记录条数):db.comment.count(userid:"1003")

默认情况下 count() 方法返回符合条件的全部记录条数

分页查询

可以使用limit()方法来读取指定数量的数据,使用skip()方法来跳过指定数量的数据。

基本语法如下所示:db.collection.find().limit(NUMBER).skip(NUMBER)

如果你想返回指定条数的记录,可以在find方法后调用limit来返回结果(TopN),默认值20,例如:db.comment.find().limit(3)

skip方法同样接受一个数字参数作为跳过的记录条数。(前N个不要),默认值是0

db.comment.find().skip(3)

需求:每页2个,第二页开始:跳过前两条数据,接着值显示3和4条数据

//第一页
db.comment.find().skip(0).limit(2)
//第二页
db.comment.find().skip(2).limit(2)
//第三页
db.comment.find().skip(4).limit(2)

总的来说跟MySQL使用差不多,用法不同罢了。

排序查询

sort() 方法对数据进行排序,sort() 方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而 -1 是用 于降序排列。

语法如下所示:db.集合名称.find().sort(排序方式)

例如:对userid降序排列,并对访问量进行升序排列:db.comment.find().sort(userid:-1,likenum:1)

skip(), limilt(), sort()三个放在一起执行的时候,执行的顺序是先 sort(), 然后是 skip(),最后是显示的 limit(),和命令编写顺序无关。

正则表达式条件查询

MongoDB的模糊查询是通过正则表达式的方式实现的。格式为:

db.集合.find(字段:/正则表达式/)

正则表达式是js的语法,直接量的写法。 例如,我要查询评论内容包含“开水”的所有文档,代码如下:db.comment.find(content:/开水/)

如果要查询评论的内容中以“专家”开头的,代码如下:db.comment.find(content:/^专家/)

比较查询

<, <=, >, >= 这个操作符也是很常用的,格式如下:

db.集合名称.find( "field" :  $gt: value ) // 大于: field > value
db.集合名称.find( "field" :  $lt: value ) // 小于: field < value
db.集合名称.find( "field" :  $gte: value ) // 大于等于: field >= value
db.集合名称.find( "field" :  $lte: value ) // 小于等于: field <= value
db.集合名称.find( "field" :  $ne: value ) // 不等于: field != value

查询评论点赞数量大于700的记录:db.comment.find(likenum:$gt:NumberInt(700))

包含查询

包含使用$in操作符。 示例:查询评论的集合中userid字段包含1003或1004的文档

db.comment.find(userid:$in:["1003","1004"])

不包含使用$nin操作符。 示例:查询评论集合中userid字段不包含1003和1004的文档:

db.comment.find(userid:$nin:["1003","1004"])

条件连接查询

我们如果需要查询同时满足两个以上条件,需要使用$and操作符将条件进行关联。(相 当于SQL的and) 格式为:$and:[ , , ]

示例:查询评论集合中likenum大于等于700 并且小于2000的文档

db.comment.find($and:[likenum:$gte:NumberInt(700),likenum:$lt:NumberInt(2000)])

如果两个以上条件之间是或者的关系,我们使用 操作符进行关联,与前面 and的使用方式相同格式为:$or:[ , , ]

查询评论集合中userid为1003,或者点赞数小于1000的文档记录:

db.comment.find($or:[ userid:"1003" ,likenum:$lt:1000 ])

常用命令小结

选择切换数据库:use articledb
插入数据:db.comment.insert(bson数据)
查询所有数据:db.comment.find();
条件查询数据:db.comment.find(条件)
查询符合条件的第一条记录:db.comment.findOne(条件)
查询符合条件的前几条记录:db.comment.find(条件).limit(条数)
查询符合条件的跳过的记录:db.comment.find(条件).skip(条数)
修改数据:db.comment.update(条件,修改后的数据) 或db.comment.update(条件,$set:要修改部分的字段:数据)
修改数据并自增某字段值:db.comment.update(条件,$inc:自增的字段:步进值)
删除数据:db.comment.remove(条件)
统计查询:db.comment.count(条件)
模糊查询:db.comment.find(字段名:/正则表达式/)
条件比较运算:db.comment.find(字段名:$gt:)
包含查询:db.comment.find(字段名:$in:[1,值2])或db.comment.find(字段名:$nin:[1,值2])
条件连接查询:db.comment.find($and:[条件1,条件2])或db.comment.find($or:[条件1以上是关于MongoDB——基础操作的主要内容,如果未能解决你的问题,请参考以下文章

mongodb基础学习4

node.js零基础详细教程:node.js操作mongodb,及操作方法的封装

node.js零基础详细教程:node.js操作mongodb,及操作方法的封装

MongoDB按“数字”升序排列

MongoDB按“数字”升序排列

MongoDB 创建基础索引组合索引唯一索引以及优化