Loading

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存储用户信息、点赞互动信息等。

 

这些应用场景中,数据操作方面的共同特点是:

(1)数据量大

(2)写入操作频繁(读写都很频繁)

(3)价值较低的数据,对事务性要求不高

对于这样的数据,我们更适合使用MongoDB来实现数据的存储。

📝 什么时候选择MongoDB

在架构选型上,除了上述的三个特点外,如果你还犹豫是否要选择它?可以考虑以下的一些问题:

应用不需要事务及复杂join支持

新应用,需求会变,数据模型无法确定,想快速迭代开发

应用需要2000-3000以上的读写QPS(更高也可以)

应用需要TB甚至 PB 级别数据存储

应用发展迅速,需要能快速水平扩展

应用要求存储的数据不丢失

应用需要99.999%高可用

应用需要大量的地理位置查询、文本查询

如果上述有1个符合,可以考虑 MongoDB,2个及以上的符合,选择 MongoDB 绝不会后悔。

 

MongoDB简介

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

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

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

 

体系结构

📝 MySQL和MongoDB的对比:

SQL术语概念 MongoDB术语/概念 解释/说明
database database 数据库
table collection 数据库表/集合
row document 数据记录行/文档
column field 数据字段/域
index index 索引
table joins 表连接,MongoDB不支持
嵌入文档 MongoDB通过嵌入式文档来替代多表连接
primary key primary key 主键,MongoDB自动将_id字段设置为主键

 

数据模型

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

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

Bson中,除了基本的JSON类型:string,integer,boolean,double,null,array和object,mongo还使用了特殊的数据类型。这些类型包括date,object id,binary data,regular expression 和code。每一个驱动都以特定语言的方式实现了这些类型,查看你的驱动的文档来获取详细信息。

BSON数据类型参考列表:

数据类型 描述 举例
字符串 UTF-8字符串都可表示为字符串类型的数据
对象id 对象id是文档的12字节的唯一ID
布尔值 真或者假:true或者false {"x":true}+
数组 值的集合或者列表可以表示成数组
32位整数 类型不可用。JavaScript仅支持64位浮点数,所以32位整数会被自动转换 shell是不支持该类型的,shell中默认会转换成64位浮点数
64位整数 不支持这个类型。shell会使用一个特殊的内嵌文档来显示64位整数 shell是不支持该类型的,shell中默认会转换成64位浮点数
64位浮点数 shell中的数字就是这一种类型
null 表示空值或者未定义的对象
undefifined 文档中也可以使用未定义类型
符号 shell不支持,shell会将数据库中的符号类型的数据自动转换成字符串
正则表达式 文档中可以包含正则表达式,采用JavaScript的正则表达式语法
代码 文档中还可以包含JavaScript代码 {"x" : function() { /* …… */ }}
二进制数据 二进制数据可以由任意字节的串组成,不过shell中无法使用
最大值/最小值 BSON包括一个特殊类型,表示可能的最大值。shell中没有这个类型

提示:

shell默认使用64位浮点型数值。{“x”:3.14}或{“x”:3}。对于整型值,可以使用NumberInt(4字节符号整数)或NumberLong(8字节符号整数),{“x”:NumberInt(“3”)}{“x”:NumberLong(“3”)}

 

MongoDB的特点

  • 高性能:

    MongoDB提供高性能的数据持久性。特别是,

    对嵌入式数据模型的支持减少了数据库系统上的I/O活动。

    索引支持更快的查询,并且可以包含来自嵌入式文档和数组的键。(文本索引解决搜索的需求、TTL索引解决历史数据自动过期的需求、地理位置索引可用于构建各种 O2O 应用)

    mmapv1、wiredtiger、mongorocks(rocksdb)、in-memory 等多引擎支持满足各种场景需求。

    Gridfs解决文件存储的需求。

  • 高可用性:

    MongoDB的复制工具称为副本集(replica set),它可提供自动故障转移和数据冗余。

  • 高扩展性:

    MongoDB提供了水平可扩展性作为其核心功能的一部分。

    分片将数据分布在一组集群的机器上。(海量数据存储,服务能力水平扩展)

    从3.4开始,MongoDB支持基于片键创建数据区域。在一个平衡的集群中,MongoDB将一个区域所覆盖的读写只定向到该区域内的那些片。

  • 丰富的查询支持:

    MongoDB支持丰富的查询语言,支持读和写操作(CRUD),比如数据聚合、文本搜索和地理空间查询等。

  • 其他特点:

    如无模式(动态模式)、灵活的文档模型、

 

MongoDB中的基本概念

📝 数据库

  • 一个mongodb中可以建立多个数据库。
  • MongoDB的默认数据库为"db",该数据库存储在data目录中
  • MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中。

📝 集合

  • 集合就是MongoDB文档组,类似于RDBMS(关系数据库管理系统:Relational Database Management System)中的表格。
  • 集合存在于数据库中,集合没有固定的结构,对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。

集合命名的时候应该注意:

  • 集合名不能是空字符串""。
  • 集合名不能含有\0字符(空字符),这个字符表示集合名的结尾。
  • 集合名不能以"system."开头,这是为系统集合保留的前缀。
  • 用户创建的集合名字不能含有保留字符。

📝 文档(document)

是一组键值(key-value)对(即BSON)。MongoDB的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是MongoDB非常突出的特点。

需要注意的是:

  • 文档中的键/值对是有序的。
  • 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型。
  • MongoDB区分类型和大小写。
  • MongoDB的文档不能有重复的键。
  • 文档的键是字符串。

 

MongoDB部署

1.下载软件包

# wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.4.1.tgz

2.解压缩

# tar -xvzf mongodb-linux-x86_64-rhel70-4.4.1.tgz
# mv mongodb-linux-x86_64-rhel70-4.4.1 /usr/local/mongodb

3.创建数据目录、日志目录、配置文件存放目录

# mkdir /usr/local/mongodb/{data,conf,log}

4.编辑配置文件

# cat >>/usr/local/mongodb/conf/mongodb.conf<<EOF
dbpath=/usr/local/mongodb/data
logpath=/usr/local/mongodb/log/mongodb.log
bind_ip=0.0.0.0
port=27017
logappend=1
fork=1
EOF

5.添加环境变量

# vim /etc/profile
export MONGODB_HOME=/usr/local/mongodb
export PATH=$PATH:$MONGODB_HOME/bin
# source /etc/profile

6.启动

# mongod --config /usr/local/mongodb/conf/mongodb.conf
# ps -ef |grep mongo
root     3969694       1  0 10:19 ?        00:01:06 mongod --config /usr/local/mongodb/conf/mongodb.conf

✏️ 停止mongodb

停止服务的方式有两种:快速关闭和标准关闭
1.快速关闭方法(快速,简单,数据可能会出错)
目标:通过系统的kill命令直接杀死进程,杀完要检查一下,避免有的没有杀掉。
通过进程编号关闭节点 
# kill -2 3969694

2.标准的关闭方法(数据不容易出错,但麻烦)
目标:通过mongo客户端中的shutdownServer命令来关闭服务
//客户端登录服务,注意,这里通过localhost登录,如果需要远程登录,必须先登录认证才行。
> mongo --port 27017 
//#切换到admin库 
> use admin 
//关闭服务 
> db.shutdownServer()

补充

如果一旦是因为数据损坏,则需要进行如下操作(了解):

1.删除lock文件

# rm -f /usr/local/mongodb/data/mongod.lock

2.修复数据

# mongod --repair --dbpath=/usr/local/mongodb/data/

 

常用命令

MongoDB库操作

📝 MongoDB系统保留库说明:

系统保留数据库:可以直接访问这些有特殊作用的数据库。

  • admin:从权限的角度来看,这是"root"数据库
  • local:这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合;
  • config:当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。

✏️ 选择和创建数据库

> use 数据库名

如果数据库不存在,则创建数据库,否则切换到指定的数据库。

> use articledb

✏️ 查看当前服务器的所有数据库

> show databases
或
> show dbs

✏️ 查看当前正在使用的数据库

> db

✏️ 删除数据库

> db.dropDatabase()

备注:主要用来删除已经持久化的数据库

注意: 要删除哪个数据库,一定要先切换到要删除的数据库中,然后再进行db.dropDatabase()

 

MongoDB集合操作

✏️ 集合的显示创建

基本语法:

> db.createCollection(name, options)

其中
- name:要创建的集合名称
- options:可选参数,指定有关内存大小及索引的选项(一下为可选参数列表)

options参数如下:

字段 类型 描述
capped 布尔 (可选)如果为true,则创建固定集合,固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。当改值为true时,必须指定size参数。
autoIndexld 布尔 (可选)如果为true,自动在_id字段创建索引。默认为true。
size 数值 (可选)为固定集合指定一个最大值,以千字节计(KB)。如果capped为true,也需要指定该字段。
max 数值 (可选)指定固定集合中包含文档的最大值。

📝 示例

创建一个集合testcol
> db.createCollection("testcol");
{ "ok" : 1 }

//创建集合student
> db.createCollection("student");
{ "ok" : 1 }

//创建固定大小的集合,创建固定集合mycol,整个集合空间大小6142800KB,文档最大个数为10000个。
> db.createCollection("mycol",{capped:true,size:6142800,max:10000});
{ "ok" : 1 }
> show tables;
mycol
student
testcol

//创建固定大小的集合,创建固定集合mycol02,整个集合空间大小6142800KB,文档最大个数为10000个。
> db.createCollection("mycol02",{capped:true,size:6142800,max:10000, autoIndexId:true});
{
	"note" : "The autoIndexId option is deprecated and will be removed in a future release",
	"ok" : 1
}

注意MongoDB中,集合只有在内容插入后才会创建! 就是说,创建集合(数据表)后要再插入一个文档(记录),集合才会真正创建。

✏️ 集合的隐式创建

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

 

✏️ 集合的查看

> show collections
或者
> show tables

 

✏️ 集合的删除

集合删除语法格式如下:

> db.collection.drop()
或
> db.集合.drop()

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

例如:要删除testcol集合

> db.testcol.drop()
true

 

文档基本CRUD

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

文档的插入

✏️ 单个文档插入

语法如下:

db.COLLECTION_NAME.insert(document)

示例:

> use testcoll
switched to db testcoll
> db.student.insert({name:"小白",age:18,sdept:"计算机系",sex:"男",createdatetime:new Date()})
WriteResult({ "nInserted" : 1 })

> db.student.find()
{ "_id" : ObjectId("5fa125ec481bd6c96002a80b"), "name" : "小白", "age" : 18, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-03T09:42:04.517Z") }

✏️ 批量文档插入

语法如下:

db.COLLECTION_NAME.insertMany([document1, document2,...])

示例:

> db.student.insertMany(
	[
		{name:"张大仙",age:19,sdept:"计算机系",sex:"男",createdatetime:new Date()},
		{name:"李太白",age:17,sdept:"计算机系",sex:"男",createdatetime:new Date()}
	]
)

{
	"acknowledged" : true,
	"insertedIds" : [
		ObjectId("5fa255ab45dc2c9556990f3f"),
		ObjectId("5fa255ab45dc2c9556990f40")
	]
}

> db.student.find()
{ "_id" : ObjectId("5fa125ec481bd6c96002a80b"), "name" : "小白", "age" : 18, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-03T09:42:04.517Z") }
{ "_id" : ObjectId("5fa255ab45dc2c9556990f3f"), "name" : "张大仙", "age" : 19, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T07:18:03.528Z") }
{ "_id" : ObjectId("5fa255ab45dc2c9556990f40"), "name" : "李太白", "age" : 17, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T07:18:03.528Z") }

 

文档的更新

语法如下:

db.COLLECTION_NAME.update(
	<query>{键名:值},
	<update>{$set:{键名:值}},
	{
	upsert:<boolean>,
	multi:<boolean>
	}
)
参数说明:
query:update的查询条件
update:update的对象和更新的操作符$set,可以理解为sql update查询内set后面的
upsert:可选,意思是,如果不存在update的记录,是否插入。true为插入,默认是false,不插入。
multi:可选,mongodb默认是false,只更新找到的第一条记录,如果为true,就把按条件查出来多条记录全部更新。

示例:

✏️ 修改匹配的第一条记录

> db.student.update(
	{sex:"男"},
	{$set:{sdept:"前端"}},
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.student.find()
{ "_id" : ObjectId("5fa125ec481bd6c96002a80b"), "name" : "小白", "age" : 18, "sdept" : "前端", "sex" : "男", "createdatetime" : ISODate("2020-11-03T09:42:04.517Z") }
{ "_id" : ObjectId("5fa255ab45dc2c9556990f3f"), "name" : "张大仙", "age" : 19, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T07:18:03.528Z") }
{ "_id" : ObjectId("5fa255ab45dc2c9556990f40"), "name" : "李太白", "age" : 17, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T07:18:03.528Z") }

✏️ 修改匹配的所有记录

> db.student.update(
	{sex:"男"},
	{$set:{sdept:"后端"}},
	{multi:true}
)
WriteResult({ "nMatched" : 3, "nUpserted" : 0, "nModified" : 3 })

> db.student.find()
{ "_id" : ObjectId("5fa125ec481bd6c96002a80b"), "name" : "小白", "age" : 18, "sdept" : "后端", "sex" : "男", "createdatetime" : ISODate("2020-11-03T09:42:04.517Z") }
{ "_id" : ObjectId("5fa255ab45dc2c9556990f3f"), "name" : "张大仙", "age" : 19, "sdept" : "后端", "sex" : "男", "createdatetime" : ISODate("2020-11-04T07:18:03.528Z") }
{ "_id" : ObjectId("5fa255ab45dc2c9556990f40"), "name" : "李太白", "age" : 17, "sdept" : "后端", "sex" : "男", "createdatetime" : ISODate("2020-11-04T07:18:03.528Z") }

✏️ 匹配多个条件(同时满足)

> db.student.update(
	{sex:"男", name:"小白"},
	{$set:{sdept:"计算机系"}},
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.student.find()
{ "_id" : ObjectId("5fa125ec481bd6c96002a80b"), "name" : "小白", "age" : 18, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-03T09:42:04.517Z") }
{ "_id" : ObjectId("5fa255ab45dc2c9556990f3f"), "name" : "张大仙", "age" : 19, "sdept" : "后端", "sex" : "男", "createdatetime" : ISODate("2020-11-04T07:18:03.528Z") }
{ "_id" : ObjectId("5fa255ab45dc2c9556990f40"), "name" : "李太白", "age" : 17, "sdept" : "后端", "sex" : "男", "createdatetime" : ISODate("2020-11-04T07:18:03.528Z") }

✏️ 更新多个值

> db.student.update(
	{sex:"男", name:"小白"},
	{$set:{sdept:"英语系", age:22}},
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.student.find()
{ "_id" : ObjectId("5fa125ec481bd6c96002a80b"), "name" : "小白", "age" : 22, "sdept" : "英语系", "sex" : "男", "createdatetime" : ISODate("2020-11-03T09:42:04.517Z") }
{ "_id" : ObjectId("5fa255ab45dc2c9556990f3f"), "name" : "张大仙", "age" : 19, "sdept" : "后端", "sex" : "男", "createdatetime" : ISODate("2020-11-04T07:18:03.528Z") }
{ "_id" : ObjectId("5fa255ab45dc2c9556990f40"), "name" : "李太白", "age" : 17, "sdept" : "后端", "sex" : "男", "createdatetime" : ISODate("2020-11-04T07:18:03.528Z") }

✏️ 多个条件满足其中一个($or)

> db.student.update(
	{$or:[{sex:19}, {name:"小白"}]},
	{$set:{sdept:"数学系", age:22}},
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.student.find()
{ "_id" : ObjectId("5fa125ec481bd6c96002a80b"), "name" : "小白", "age" : 22, "sdept" : "数学系", "sex" : "男", "createdatetime" : ISODate("2020-11-03T09:42:04.517Z") }
{ "_id" : ObjectId("5fa255ab45dc2c9556990f3f"), "name" : "张大仙", "age" : 19, "sdept" : "后端", "sex" : "男", "createdatetime" : ISODate("2020-11-04T07:18:03.528Z") }
{ "_id" : ObjectId("5fa255ab45dc2c9556990f40"), "name" : "李太白", "age" : 17, "sdept" : "后端", "sex" : "男", "createdatetime" : ISODate("2020-11-04T07:18:03.528Z") }

 

文档的删除

语法如下:

db.COLLECTION_NAME.remove(
	<query>,
	{
	justOne:<boolean>
	}
)

参数说明:
query:(可选)删除的文档的条件,
justOne:(可选)如果设置为true或1,则只删除一个文档,如果不设置该参数,或使用默认值false,则删除所有匹配条件的文档。

示例:

✏️ 删除符合条件的第一条(justOne.true)

> db.student.remove(
	{sex:"男"},
	{justOne:true}
)
WriteResult({ "nRemoved" : 1 })

> db.student.find()
{ "_id" : ObjectId("5fa255ab45dc2c9556990f3f"), "name" : "张大仙", "age" : 19, "sdept" : "后端", "sex" : "男", "createdatetime" : ISODate("2020-11-04T07:18:03.528Z") }
{ "_id" : ObjectId("5fa255ab45dc2c9556990f40"), "name" : "李太白", "age" : 17, "sdept" : "后端", "sex" : "男", "createdatetime" : ISODate("2020-11-04T07:18:03.528Z") }

✏️ 删除符合条件的所有记录

> db.student.remove(
	{sex:"男"}
)

✏️ 删除所有记录

> db.student.remove({})

 

文档的查询

MongoDB查询文档使用find()方法,使用findOne()查询一条数据

find()方法以非结构化的方式来显示所有的文档

语法格式:

db.COLLECTION_NAME.find(query,projection)

注意:
query:可选,使用查询操作符指定查询条件
projection:可选,使用投影操作符指定返回的值
需要以格式化的方式来读取数据,可以使用pretty()方法。

查询前先造几条数据

db.student.insertMany(
	[
		{name:"张大仙",age:19,sdept:"计算机系",sex:"男",createdatetime:new Date()},
		{name:"李太白",age:17,sdept:"计算机系",sex:"男",createdatetime:new Date()},
		{name:"黄花",age:18,sdept:"英语系",sex:"女",createdatetime:new Date()},
		{name:"菜花",age:20,sdept:"数学系",sex:"女",createdatetime:new Date()},
	]
)

基本查询

✏️ 查询student集合中所有的文档

> db.student.find()
{ "_id" : ObjectId("5fa27688b808fba58f5a3a41"), "name" : "张大仙", "age" : 19, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T09:38:16.820Z") }
{ "_id" : ObjectId("5fa27688b808fba58f5a3a42"), "name" : "李太白", "age" : 17, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T09:38:16.820Z") }
{ "_id" : ObjectId("5fa27688b808fba58f5a3a43"), "name" : "黄花", "age" : 18, "sdept" : "英语系", "sex" : "女", "createdatetime" : ISODate("2020-11-04T09:38:16.820Z") }
{ "_id" : ObjectId("5fa27688b808fba58f5a3a44"), "name" : "菜花", "age" : 20, "sdept" : "数学系", "sex" : "女", "createdatetime" : ISODate("2020-11-04T09:38:16.820Z") }

✏️ 格式化方法显示查询结果

> db.student.find().pretty()
{
	"_id" : ObjectId("5fa27688b808fba58f5a3a41"),
	"name" : "张大仙",
	"age" : 19,
	"sdept" : "计算机系",
	"sex" : "男",
	"createdatetime" : ISODate("2020-11-04T09:38:16.820Z")
}
{
	"_id" : ObjectId("5fa27688b808fba58f5a3a42"),
	"name" : "李太白",
	"age" : 17,
	"sdept" : "计算机系",
	"sex" : "男",
	"createdatetime" : ISODate("2020-11-04T09:38:16.820Z")
}
{
	"_id" : ObjectId("5fa27688b808fba58f5a3a43"),
	"name" : "黄花",
	"age" : 18,
	"sdept" : "英语系",
	"sex" : "女",
	"createdatetime" : ISODate("2020-11-04T09:38:16.820Z")
}
{
	"_id" : ObjectId("5fa27688b808fba58f5a3a44"),
	"name" : "菜花",
	"age" : 20,
	"sdept" : "数学系",
	"sex" : "女",
	"createdatetime" : ISODate("2020-11-04T09:38:16.820Z")
}

✏️ 条件过滤查询

> db.student.find({sex:"男"})
{ "_id" : ObjectId("5fa27688b808fba58f5a3a41"), "name" : "张大仙", "age" : 19, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T09:38:16.820Z") }
{ "_id" : ObjectId("5fa27688b808fba58f5a3a42"), "name" : "李太白", "age" : 17, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T09:38:16.820Z") }

✏️ 查询一条记录

> db.student.findOne()
{
	"_id" : ObjectId("5fa27688b808fba58f5a3a41"),
	"name" : "张大仙",
	"age" : 19,
	"sdept" : "计算机系",
	"sex" : "男",
	"createdatetime" : ISODate("2020-11-04T09:38:16.820Z")
}

 

条件查询

✏️ 多个条件同时满足查询 $and

db.COLLECTION_NAME.find({K1:V1,K2:V2,K3:V3...})
或者
db.COLLECTION_NAME.find({$and:[{K1:V1},{K2:V2},{K3:V3}...]})

示例:

# 查询年龄为19,而且性别为男的学生
> db.student.find({age:19,sex:"男"})
{ "_id" : ObjectId("5fa27688b808fba58f5a3a41"), "name" : "张大仙", "age" : 19, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T09:38:16.820Z") }

> db.student.find({$and:[{age:19},{sex:"男"}]})
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4b"), "name" : "张大仙", "age" : 19, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }

✏️ 多个条件只是满足其中一个 $or

db.COLLECTION_NAME.find({$or:[{K1:V1},{K2:V2},{K3:V3}...]})

示例:

# 查询年龄是19或者为英语系的学生
> db.student.find({$or:[{age:19},{sdept:"英语系"}]})
{ "_id" : ObjectId("5fa27688b808fba58f5a3a41"), "name" : "张大仙", "age" : 19, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T09:38:16.820Z") }
{ "_id" : ObjectId("5fa27688b808fba58f5a3a43"), "name" : "黄花", "age" : 18, "sdept" : "英语系", "sex" : "女", "createdatetime" : ISODate("2020-11-04T09:38:16.820Z") }

✏️ 根据数据类型来匹配对应的结果$type

db.COLLECTION_NAME.find({KEY:{$type:数字或者数据类型}})

$tpye操作符,MongoDB中可以使用的类型如下表所示:

类型 数字 备注
Double 1
String 2
Object 3
Array 4
Binary data 5
Undefined 6 已废弃
Object id 7
Boolean 8
Date 9
Null 10
Regular Expression 11
JavaScript 13
Symbol 14
JavaScript (with scope) 15
32-bit integer 16
Timestamp 17
64-bit integer 18
Min key 255 Query with -1
Max key 127

示例:

# 这里先插入一条数据进行测试
> db.student.insert({name:12,age:28,sdept:"体育系",createdatetime:new Date()})
WriteResult({ "nInserted" : 1 })

# 查询名字类型为Double类型的学生
> db.student.find({name:{$type:1}})
{ "_id" : ObjectId("5fa36936bde0f17be2c81931"), "name" : 12, "age" : 28, "sdept" : "体育系", "createdatetime" : ISODate("2020-11-05T02:53:42.760Z") }

✏️ 读取指定数量的数据记录limit()

db.COLLECTION_NAME.find().limit(NUMBER)

NUMBER:表示记录条数,默认值为20

示例:

# 查询性别为男学生前2条记录
> db.student.find({sex:"男"}).limit(1)
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4b"), "name" : "张大仙", "age" : 19, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }

✏️ 查询出来的记录,跳过指定数量的前多少条记录skip()

db.COLLECTION_NAME.find().skip(NUMBER)
或者
db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)

备注:skip(NUMBER)中的NUMBER默认值为0

示例:

# 查询所有的性别为男的学生信息并跳过第一条记录
> db.student.find({sex:"男"}).skip(1)
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4c"), "name" : "李太白", "age" : 17, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }

# 查询前两条性别为男的学生信息,跳过第一条记录
> db.student.find({sex:"男"}).limit(2).skip(1)
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4c"), "name" : "李太白", "age" : 17, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }

✏️ 对查询出来的记录进行排序 sort()

db.COLLECTION_NAME.find().sort({key:1})
或者
db.COLLECTION_NAME.find().sort({key:-1})

备注:sort()方法可以通过参数指定排序的字段,并使用1和-1来指定排序的方式,其中1为升序排列,而-1为降序排列。

示例:

# 查询所有学生信息,按照年龄升序排列
> db.student.find().sort({age:1})
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4c"), "name" : "李太白", "age" : 17, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4d"), "name" : "黄花", "age" : 18, "sdept" : "英语系", "sex" : "女", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4b"), "name" : "张大仙", "age" : 19, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4e"), "name" : "菜花", "age" : 20, "sdept" : "数学系", "sex" : "女", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa36936bde0f17be2c81931"), "name" : 12, "age" : 28, "sdept" : "体育系", "createdatetime" : ISODate("2020-11-05T02:53:42.760Z") }

# 查询所有学生信息,按照年龄降序排列
> db.student.find().sort({age:-1})
{ "_id" : ObjectId("5fa36936bde0f17be2c81931"), "name" : 12, "age" : 28, "sdept" : "体育系", "createdatetime" : ISODate("2020-11-05T02:53:42.760Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4e"), "name" : "菜花", "age" : 20, "sdept" : "数学系", "sex" : "女", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4b"), "name" : "张大仙", "age" : 19, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4d"), "name" : "黄花", "age" : 18, "sdept" : "英语系", "sex" : "女", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4c"), "name" : "李太白", "age" : 17, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }

 

比较查询

✏️ 大于查询 $gt

db.COLLECTION_NAME.find({KEY:{$gt:value}})

示例:

# 查询年龄大于17的学生
> db.student.find({age:{$gt:17}})
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4b"), "name" : "张大仙", "age" : 19, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4d"), "name" : "黄花", "age" : 18, "sdept" : "英语系", "sex" : "女", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4e"), "name" : "菜花", "age" : 20, "sdept" : "数学系", "sex" : "女", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }

✏️ 小于查询$lt

db.COLLECTION_NAME.find({KEY:{$lt:value}})

示例:

# 查询年龄小于20的学生
> db.student.find({age:{$lt:20}})
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4b"), "name" : "张大仙", "age" : 19, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4c"), "name" : "李太白", "age" : 17, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4d"), "name" : "黄花", "age" : 18, "sdept" : "英语系", "sex" : "女", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }

✏️ 大于等于查询 $gte

db.COLLECTION_NAME.find({KEY:{$gte:value}})

示例:

# 查询年龄大于等于17的学生
> db.student.find({age:{$gte:17}})
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4b"), "name" : "张大仙", "age" : 19, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4c"), "name" : "李太白", "age" : 17, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4d"), "name" : "黄花", "age" : 18, "sdept" : "英语系", "sex" : "女", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4e"), "name" : "菜花", "age" : 20, "sdept" : "数学系", "sex" : "女", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }

✏️ 小于等于查询 $lte

db.COLLECTION_NAME.find({KEY:{$lte:value}})

示例:

# 查询年龄小于等于20的学生
> db.student.find({age:{$lte:20}})
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4b"), "name" : "张大仙", "age" : 19, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4c"), "name" : "李太白", "age" : 17, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4d"), "name" : "黄花", "age" : 18, "sdept" : "英语系", "sex" : "女", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4e"), "name" : "菜花", "age" : 20, "sdept" : "数学系", "sex" : "女", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }

✏️ 不等于查询 $ne

db.COLLECTION_NAME.find({KEY:{$ne:value}})

示例:

# 查询年龄不等于20的学生
> db.student.find({age:{$ne:20}})
db.student.find({age:{$ne:20}})
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4b"), "name" : "张大仙", "age" : 19, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4c"), "name" : "李太白", "age" : 17, "sdept" : "计算机系", "sex" : "男", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4d"), "name" : "黄花", "age" : 18, "sdept" : "英语系", "sex" : "女", "createdatetime" : ISODate("2020-11-04T12:25:49.893Z") }

综合示例:

# 查询年龄在17~19之间的学生
> db.student.find({age:{$gt:17,$lt:19}})
# 查询年龄小于18,大于19的学生
> db.student.find({$or:[{age:{$lt:18}},{age:{$gt:19}}]})

 

查询已什么开头

格式如下:

db.COLLECTION_NAME.find({<key>:/^value/})

参数说明:
key:要查询的字段的名称
value:检查key字段的值中是否以value开始,格式:/^value/,斜杠“/”和“^”不能省略

示例:

rs0:PRIMARY> db.person.find({cid:/^512721/})
{ "_id" : ObjectId("5f0d09c4fc3df4986e62930c"), "cid" : "5127xxxxxx114702", "name" : "xxx", "createtime" : NumberLong(1594689988), "updatetime" : NumberLong(1604285711), "cid_type" : "10" }

 

查询某个字段总是否包含另一个值

格式如下:

db.COLLECTION_NAME.find({<key>:/value/})

参数说明:
key:要查询的字段的名称
value:查询key字段的值中是否包含着value的值,格式:/value/,前后的两个斜杠“/”不能省略

示例:

rs0:PRIMARY> db.person.find({name:/刘备/})
{ "_id" : ObjectId("5eb3e60ec158d2459d85aaab"), "cid" : "4208xxxx319", "name" : "刘备", "createtime" : NumberLong(1588848142), "updatetime" : NumberLong(1595218336), "cid_type" : "10" }
{ "_id" : ObjectId("5f1d4d75c158d2459d912d75"), "cid" : "4290xxxxx96", "name" : "刘备", "createtime" : NumberLong(1595755893), "updatetime" : NumberLong(1595755893), "cid_type" : "10" }
{ "_id" : ObjectId("5f0e542519c15a619088adf3"), "cid" : "510xxxxxx21", "name" : "徐刘备", "createtime" : NumberLong(1594774565), "updatetime" : NumberLong(1604016893), "cid_type" : "10" }

 

聚合查询

MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。

格式如下:

db.COLLECTION_NAME.aggregate([
	{
		管道:{聚合操作表达式}
	}
])

管道:就是把找到的数据进行过滤的操作,常用的管道符如下表

管道符 描述
$project 修改输入文档的结构。可以用来重命名、增加或删除域
$match 用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作
$limit 用来限制MongoDB聚合管道返回的文档数
$skip 在聚合管道中跳过指定数量的文档,并返回余下的文档
$group 将集合中的文档分组,可用于统计结果
$sort 将输入文档排序后输出

常用聚合表达式

表达式 描述
$sum 计算总和
$avg 计算平均值
$min 获取集合中所有文档对应值的最小值
$max 获取集合中所有文档对应值的最大值

✏️ 分组$group

db.集合名字.aggregate([
	{
		$group:{_id:"$字段名",聚合函数的别名:{聚合表达式:"$字段名"}}
	}
])

示例:

# 统计学生信息男生和女生的总年龄
> db.student.aggregate([
	{
		$group:{_id:"$sex",成绩总和:{$sum:"$age"}}
	}
])

{ "_id" : "女", "成绩总和" : 38 }
{ "_id" : "男", "成绩总和" : 36 }


# 统计学生信息男生和女生各有多少人
> db.student.aggregate([
	{
		$group:{_id:"$sex",总人数:{$sum:1}}
	}
])

{ "_id" : "女", "总人数" : 2 }
{ "_id" : "男", "总人数" : 2 }

//备注:$sum:1 等于MySQL的count(*) 统计总的记录数


# 求学生的总数和平均年龄
> db.student.aggregate([
	{
		$group:{_id:null,人数:{$sum:1},平均年龄:{$avg:"$age"}}
	}
])

{ "_id" : null, "人数" : 4, "平均年龄" : 18.5 }


# 求男生或者女生的总数和平均年龄
> db.student.aggregate([
	{
		$group:{_id:"$sex",人数:{$sum:1},平均年龄:{$avg:"$age"}}
	}
])
{ "_id" : "女", "人数" : 2, "平均年龄" : 19 }
{ "_id" : "男", "人数" : 2, "平均年龄" : 18 }


# 查询男生和女生的人数,按人数升序排列
> db.student.aggregate([
	{
		$group:{_id:"$sex",总人数:{$sum:1}}
	},
	{
		$sort:{总人数:1}
	}
])


# 查询年龄小于等19,只看两条记录
> db.student.find({age:{$lte:19}}).limit(2)		#普通方法
# 管道的方法
> db.student.aggregate([
	{
		$match:{age:{$lte:19}}
	},
	{$limit:2}
])


# 查看男生的最大年龄
> db.student.aggregate([
	{
		$match:{sex:"男"}
	},
	{
		$group:{_id:"$sex", 最高分:{$max:"$age"}}
	}
])


# 修改文档结构,只含有_id,name,age
> db.student.aggregate([
	{
		$project:{name:1,age:1}
	}
])
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4b"), "name" : "张大仙", "age" : 19 }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4c"), "name" : "李太白", "age" : 17 }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4d"), "name" : "黄花", "age" : 18 }
{ "_id" : ObjectId("5fa29dcd8b194ee77bc32b4e"), "name" : "菜花", "age" : 20 }
//备注:在$project,字段名:1 ---->获取该字段的所有内容
//等于MySQL中的 select name,age from student;

 

去重统计查询

根据指定字段进行去重,然后统计总数

> db.person.aggregate([
    {"$group": {"_id": "$cid"}},
    {"$group": {"_id": null, "counts": {"$sum": 1}}}
])

# 说明:
第一个group进行分组,中的"_id"指定需要去重的字段名称,这里根据cid进行去重
第二个group进行统计,中的"_id"可为空,也可为null

 

常用命令总结

# 选择切换数据库:
use DB_NAME

# 插入数据:
db.COLLECTION_NAME.insert({bson数据})

# 查询所有数据:
db.COLLECTION_NAME.find()

# 格式化显示查询的数据:
db.COLLECTION_NAME.find().pretty()

# 条件查询数据:
db.COLLECTION_NAME.find({K1:V1,K2:V2...})

# 查询符合条件的第一条记录:
db.COLLECTION_NAME.findOne({K1:V1,K2:V2...})

# 查询符合条件的前几条记录:
db.COLLECTION_NAME.find({K1:V1,K2:V2...}).limit(条数)

# 查询符合条件的跳过的记录:
db.COLLECTION_NAME.find({K1:V1,K2:V2...}).skip(条数)

# 查询满足多个条件中任意条件的记录:
db.COLLECTION_NAME.find({$or:[{K1:V1},{K2:V2},{K3:V3}...]})

# 对查询结果进行升序排序
db.COLLECTION_NAME.find().sort({kEY:1})

# 对查询结果进行降序排序
db.COLLECTION_NAME.find().sort({kEY:-1})

# 大于查询
db.COLLECTION_NAME.find({KEY:{$gt:value}})

# 小于查询
db.COLLECTION_NAME.find({KEY:{$lt:value}})

# 大于等于查询
db.COLLECTION_NAME.find({KEY:{$gte:value}})

# 小于等于查询
db.COLLECTION_NAME.find({KEY:{$lte:value}})

# 不等于查询
db.COLLECTION_NAME.find({KEY:{$ne:value}})

# 查询大于小于之间的数据记录
db.COLLECTION_NAME.find({KEY:{$gt:NUMBER,$lt:NUMBER}})

# 查询小于多少,或者大于多少的数据
db.COLLECTION_NAME.find({$or:[{KEY:{$lt:NUMBER}},{KEY:{$gt:NUMBER}}]})

# 统计查询
db.COLLECTION_NAME.find().count()

# 查询已什么开头
db.COLLECTION_NAME.find({<key>:/^value/})
或者:
db.COLLECTION_NAME.find({<key>: {"$regex": "^value"}})

# 查询某个字段总是否包含另一个值
db.COLLECTION_NAME.find({<key>:/value/})

# 根据指定字段去重并统计总数
db.person.aggregate([
    {"$group": {"_id": "$cid"}},
    {"$group": {"_id": null, "counts": {"$sum": 1}}}
])
posted @ 2020-11-13 09:25  别来无恙-  阅读(716)  评论(0编辑  收藏  举报