springboot 条件查询mongodb中最新的一条数据 mongodb条件查询效率_mongodb

MongoDB安装与快速入门



一、前言

MongoDB是一个基于分布式文件存储的数据库,介于关系型数据库与非关系型数据库之间,是非关系数据库中功能最丰富,最像关系型数据库的。它支持的结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。MongoDB最大的特点是它支持的查询非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系型数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

  • Document(文档): 是MongoDB中数据的基本单元,它非常类似于关系型数据库中的数据行。
  • Collection(集合): 可以看作是一个拥有动态模式的表。
  • MongoDB的一个实例可以拥有多个相互独立的数据库(database), 每一个数据库都拥有自己的集合。
  • 每个文档都有一个特殊的键`_id`, 这个键在文档所属的集合中是唯一的。

1.1. MongoDB

  • MongoDB是一个基于分布式文件存储的NoSQL数据库
  • 由c++语言编写,运行稳定,性能高
  • 旨在为web应用提供可扩展的高性能的数据存储解决方案

1.2. MongoDB特点

  • 模式自由 :可以把不同结构的文档存储在同一个数据库里
  • 面向集合的存储:适合存储 JSON风格文件的形式
  • 完整的索引支持:对任何属性可索引
  • 复制和高可用性:支持服务器之间的数据复制,支持主-从模式及服务器之间的相互复制。复制的主要目的是提供冗余及自动故障转移
  • 自动分片:支持云级别的伸缩性:自动分片功能支持水平的数据库集群,可动态添加额外的机器
  • 丰富的查询:支持丰富的查询表达方式,查询指令使用JSON形式的标记,可轻易查询文档中的内嵌的对象及数组
  • 快速就地更新:查询优化器会分析查询表达式,并生成一个高效的查询计划
  • 高效的传统存储方式:支持二进制数据及大型对象(如照片或图片)

1.3.MongoDB与SQL名词解释与对比




springboot 条件查询mongodb中最新的一条数据 mongodb条件查询效率_mongodb_02

MongoDB术语与关系型SQL对比



  • document: 文档,就是一个对象,由键值对构成,是json的扩展bson形式
{'name':'杨过', 'gender':'男'}
  • collection: 集合,类似于关系型数据库中的表,存储多个文档,结构不固定
{'name':'风清扬', 'age': 55, 'gender': '男'}  {'name':'令狐冲', 'age': 32, 'gender': '男', 'partner':'小龙女'}  {'name':'乔峰', 'age':40, 'gender': '男', 'kongfu':'响龙十八掌'}
  • database: 数据库,是一个集合的物理容器,一个数据库中可以包含多个集合。

二、文档

文档是MongoDB中的核心概念。文档就是键值对的一个有序集。每种编程语言表示文档的方法不太一样,但是大多数编程语言都有一些通用的数据结构,比如映射map、散列hash、字典等。例如:

{"name": "风清扬", "age": 54, "gender":"男"}

MongoDB不但区分类型,还区分大小写,比如下面的两个文档是不同的:

# 区分大小写{"name": "terminator"}{"Name": "terminator"}# 区分类型{"age": "54"}{"age": 54}

MongoDB中的键不能重复,例如下面的文档是非法的:

{"name":"zhangsanfeng", "name":"zhangwuji", "age":56}

MongoDB中键/值是有顺序的,例如,下面的两个文档也是不同的

{"name":"linqingxia", "age": 52}{"age": 52, "name":"linqingxia"}

三、集合

集合就是有一组文档组成,相当于关系型数据库中表的概念。而文档就相当于关系型数据库表中的一行记录。

3.1.动态模式

集合是动态模式的,这就意味着集合里的文档可以是各式各样的,不需要每个文档具有相同的键。例如:

{"name":"张无忌", "kongfu":"九阳神功", "age": 25}{"department":"账务部"}

需要注意的是,上面的文档有不同值的类型、键的个数和键的名称完全不相同。因为集合里面可以放置任何文档,随之而来的一个问题是:还有必要使用多个集合吗?这里有几个重要的原因:

  • 如果把不同文档不加以任何区分放在同一个集合里,无论对开发者还是管理者来说都非常困难。
  • 在一个集合里查询特定类型的文档在速度上将消耗很大资源,分成多个集合后可以提高查询效率。
  • 把同种类型的文档放在一个集合里,数据会更加集中。
  • 创建索引时,需要使用文档的附加结构(特别是创建唯一索引时)。索引是按照集合来定义的。在一个集合中放入一种类型的文档,可以更加有效地对集合进行索引与操作。

3.2. 集合的命名规则

如同关系型数据库中的表一样,集合使用名称进行标识。集合名称可以是满足下面条件的任意UTF-8字符串。

  • 集合名称不能是空的字符串"";
  • - 集合名称不能包含0字符(空字符),这个字符表示集合名的结束。
  • - 集合名不能以"system."开头,这是为系统集合保留的前缀。例如:system.users这个集合保存着用户的基本信息。
  • - 用户创建的集合最好不要在集合名称中包含"$"符号。因为某些系统生成的集合中包含"$"符号。

3.2.1.子集合

组织集合的一种惯例是使用"."来分隔不同命名空间的子集合。例如,一个具有博客功能的应用可能包含两个集合,分别是blog.posts和blog.authors。这样划分是为了使组织结构更加清晰,这里的blog集合(这个集合甚至不需要存在)跟它的子集合没有任何关系。

虽然子集合没有任何特别的属性,但它们非常有用,因而很多的MongoDB工具都使用子集合。

  • GridFS(一种用于存储大文件的协议)使用子集合来存储文件的元数据,这样可以与文件内容很好地隔离开来。
  • 大多数MongoDB数据库的驱动程序提供了一些语法糖,用于访问指定集合的子集合。例如MongoDB数据库的shell中,db.blog代表blog集合,而db.blog.posts代表blog.posts子集合。

在MongoDB中,使用子集合来组织数据非常高效,值得推荐使用子集合。

四、数据库

在MongoDB中,多个文档组成集合,而多个集合则可以组成数据库。一个MongoDB实例可以承载多个数据库,每个数据库可以包含0个或多个集合。每个数据库拥有独立的权限,即便是在磁盘上,不同的数据库在物理上也存储在不同的文件中。

和关系型数据库一样,通过名称来标识数据库名,数据库的命名可以是满足下面条件的任意UTF-8字符串:

  • 不能是空字符串”“
  • 不得含有(/,, ",*,,:,|,?,$)等特殊字符。基本上使用ASCII中的字母和数字。
  • 数据库名称区分大小写,一般来说,数据库名全用小写名称。
  • 数据库名称最多64个字节。

数据库最终对应系统中的文件,而数据库名称就是文件的名称,这也是数据库名称命名需要这么多限制的根本原因。

另外,MongoDB保留了一些数据库名称,这些数据库有特殊的用途:

  • admin: 从身份验证的角度来看,这是一个`root`数据库。如果将一个用户添加到admin数据库,这个用户将自动获得所有数据库的权限。另外,一些特定服务器端的命令也只能从admin数据库运行,如列出所有数据库或关闭服务器等。
  • local: 这个数据库永远都不可以复制,且一台服务器上的所有本地集合都可以存储在这个数据库中。
  • config: MongoDB用于分片设置时,分片信息会存储在config数据库中。

五、MongoDB的安装与配置

在Ubuntu下MongoDB的安装非常简单,无需下载源文件,可以直接使用`apt-get`命令进行安装。

  • 安装mongodb命令
(base) hadoop@node1:~$ sudo apt-get install mongodb




springboot 条件查询mongodb中最新的一条数据 mongodb条件查询效率_mongodb_03

MongoDB shell



  • 查看mongodb版本命令
# 查看mongodb的版本信息(base) hadoop@node1:~$ mongo -version




springboot 条件查询mongodb中最新的一条数据 mongodb条件查询效率_mongodb_04

MongoDB版本



  • 查看mongodb启动状态命令
# 查看mongodb启动状态(base) hadoop@node1:~$ sudo systemctl status mongodb




springboot 条件查询mongodb中最新的一条数据 mongodb条件查询效率_数据库_05

MongoDB启动状态



  • 关闭mongodb命令
(base) hadoop@node1:~$ sudo systemctl stop mongodb
  • 启动mongodb命令
(base) hadoop@node1:~$ sudo systemctl start mongodb

默认情况下MongoDB是随ubuntu启动的,可以通过以下命令查看

(base) hadoop@node1:~$ pgrep mongo -l




springboot 条件查询mongodb中最新的一条数据 mongodb条件查询效率_mongodb_06

pgrep mongo -l



  • 卸载MongoDB命令
$ sudo apt-get --purge remove mongodb mongodb-clients mongodb-server

六、MongoDB Shell简介

MongoDB自带了JavaScript shell, 可以在shell中使用命令行与MongoDB实时交互。shell非常有用,通过它可以执行某些对MongoDB的管理操作,检查运行的实例等。

运行`mongo`启用shell:




springboot 条件查询mongodb中最新的一条数据 mongodb条件查询效率_数据库_07

mongo命令启动shell



启动shell时,shell将自动连接MongoDB服务器,在启动MongoDB shell前,确保mongod服务已启动。shell是一个功能完备的JavaScript解释器,可以运行任意的JavaScript程序,例如:

> a = 100100> a/520> Math.sin(Math.PI/2)1> new Date()ISODate("2020-07-30T06:15:30.924Z")> "Hi MongoDB, Hi Python".replace("Python","Mongo");Hi MongoDB, Hi Mongo> function factorial(n) {... if(n<=1) return 1;... return n*factorial(n-1);... }> factorial(5)120

6.2.MongoDB客户端

MongoDB shell可以运行任意的JavaScript脚本听上去很酷,不过它的真正强大之处在于,它是一个独立的MongoDB客户端,在shell启动时,它会连接到MongoDB服务器的`test`数据库,并将数据库连接赋值给全局变量db。这个全局变量是通过shell访问MongoDB的主要入口点。

例如下面的命令:

# 查看db当前指向哪个数据库> dbtest# 列出当前MongoDB中有哪些数据库> show dbsadmin   0.000GBconfig  0.000GBcrm     0.000GBlocal   0.000GB# 切换数据库> use crmswitched to db crm

6.3.shell中的基本操作

在shell中查看或操作数据会用到4个基本操作:创建、读取、更新和删除。即通常所说的`CRUD`。

  • 创建

`insert`可以将一个文档添加到集合中。

> use movieswitched to db movie> actor = {"name":"乔峰","age":40, "movie":"天龙八部","author":"金庸","kongfu":"响龙十八掌","department":"丐帮"}{"name" : "乔峰","age" : 40,"movie" : "天龙八部","author" : "金庸","kongfu" : "响龙十八掌","department" : "丐帮"}> db.movie.actors.insert(actor)WriteResult({ "nInserted" : 1 })> db.movie.actors.find(){ "_id" : ObjectId("5f226c49a20e34cfb8a8ab33"), "name" : "乔峰", "age" : 40, "movie" : "天龙八部", "author" : "金庸", "kongfu" : "响龙十八掌", "department" : "丐帮" }> actor = {"name":"段誉","age":34, "movie":"天龙八部","author":"金庸","kongfu":"六脉神剑","department":"大理国"}{"name" : "段誉","age" : 34,"movie" : "天龙八部","author" : "金庸","kongfu" : "六脉神剑","department" : "大理国"}> db.movie.actors.insert(actor)WriteResult({ "nInserted" : 1 })> db.movie.actors.find(){ "_id" : ObjectId("5f226c49a20e34cfb8a8ab33"), "name" : "乔峰", "age" : 40, "movie" : "天龙八部", "author" : "金庸", "kongfu" : "响龙十八掌", "department" : "丐帮" }{ "_id" : ObjectId("5f226d25a20e34cfb8a8ab34"), "name" : "段誉", "age" : 34, "movie" : "天龙八部", "author" : "金庸", "kongfu" : "六脉神剑", "department" : "大理国" }>
  • 读取

find()和fineOne()都可以用于查询集合中的文档。若只需要查看一个文档使用findOne()。

> db.movie.actors.findOne(){"_id" : ObjectId("5f226c49a20e34cfb8a8ab33"),"name" : "乔峰","age" : 40,"movie" : "天龙八部","author" : "金庸","kongfu" : "响龙十八掌","department" : "丐帮"}
  • 更新

可以使用update更新文档,update至少需要两个参数:第一个是限定条件(限定集合中待更新的文档),第二个是新的文档。

> actor.comments = ['很厉害','妹子好多啊'][ "很厉害", "妹子好多啊" ]> db.movie.actors.update({"name":"段誉"}, actor)WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })> db.movie.actors.find(){ "_id" : ObjectId("5f226c49a20e34cfb8a8ab33"), "name" : "乔峰", "age" : 40, "movie" : "天龙八部", "author" : "金庸", "kongfu" : "响龙十八掌", "department" : "丐帮" }{ "_id" : ObjectId("5f226d25a20e34cfb8a8ab34"), "name" : "段誉", "age" : 34, "movie" : "天龙八部", "author" : "金庸", "kongfu" : "六脉神剑", "department" : "大理国", "comments" : [ "很厉害", "妹子好多啊" ] }>
  • 删除

使用remove方法可以将文档从数据库中永久删除。如果没有任何参数,它会将集合内的所有文档全部删除。它也可以接受一个作为限定条件的文档作为参数。例如:

> db.movie.actors.remove({"name":"段誉"})

后记

由于MongoDB的内容比较多,接下来会分几篇文章讲解MongoDB的数据类型、查询操作等内容。