MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介

对于社交类软件的功能,我们需要对它的功能特点进行分析:

  • 数据量会随着用户数增大而增大
  • 读多写少
  • 价值较低
  • 非好友看不到其动态信息
  • 地理位置的查询

针对以上特点进行分析各大存储工具:

  • mysql:关系型数据库(效率低)
  • reids: redis缓存(微博,效率高,数据格式不丰富)
  • 对于大量数据而言,显然不能使用关系型数据库进行存储,我们需要通过MongoDB进行存储
  • 对于读多写少的应用我们需要减少读取成本,比如说:一条SQL语句,单表查询一定比多表查询更快

针对社交app,一般采用一下存储策略:

  • mongodb:存储业务数据(圈子,推荐的数据,小视频数据,点赞,评论等)
  • redis:承担的角色是缓存层(提升查询效率)
  • mysql:存储和核心业务数据,账户

而对于mongoDB

  • MongoDB是一个高效的非关系型数据库(不支持表关系:只能操作单表)
  • MongoDB是一个基于分布式文件存储的数据库,由C++语言编写,旨在为WEB应用提供可扩展性高性能数据存储解决方案
  • MongoDB是一个介于关系型数据库和非关系型数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的,它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。
  • MongoDB最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
  • 官网: 添加链接描述

二丶MongoDB的特点

MongoDB 最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。它是一个面向集合的,模式自由的文档型数据库。具体特点总结如下:

  1. 面向集合存储,易于存储对象型数据
  2. 模式自由
  3. 支持动态查询
  4. 支持完全索引,包含内部对象
  5. 支持复制和故障恢复
  6. 使用高效的二进制数据存储,包括大型对象(如视频等)
  7. 自动处理碎片,以支持云计算层次的扩展性
  8. 支持 Python,PHP,Ruby,Java,C,C#,Javascript,Perl及C++语言的驱动程 序, 社区中也提供了对Erlang及.NET 等平台的驱动程序
  9. 文件存储格式为 BSON(一种 JSON 的扩展)

2.1通过docker 安装MongoDB

拉取mongodb的镜像,也可以通过docker-compose启动,更方便:
在这里插入图片描述

docker-compose up -d
#查看容器
docker ps -a

在这里插入图片描述

2.2 MongoDB体系结构

MongoDB的罗杰结构是一种层次结构,主要由文档(document),集合(collection),数据库(databases)三部分组成,逻辑结构是,面向用户的,用户使用MongoDB开发应用程序就是使用这样结构:

  1. MongoDB 的文档(document),相当于关系数据库中的一行记录。
  2. 多个文档组成一个集合(collection),相当于关系数据库的表
  3. 多个集合(collection),逻辑上组织在一起,就是数据库
  4. 应该MongoDB示例支持多个数据库database.文档document,集合collection
    类似这样:在这里插入图片描述
    为了更好的理解,可以与SQL中的概念进行对比
SQL术语/概念MongoDB术语/概念解释/说明
databasedatabase数据库
tablecollection数据库表/集合
rowdocument表中的一条数据
columnfield数据字段/域
indexindex索引
table joins表连接,MongoDB不支持
primary keyprimary key主键,MongoDB自动将_id字段设置为主键

2.3 数据类型

  • 数据格式:BSON{aa:bb}
  • null:用于表示空值或者不存在的字段,{“x”:null}
  • 布尔型:布尔类型有两个值true和false,{“x”:true}
  • 数值,shell默认使用64位浮点型数值。{“x”:3.14}或{“x”:3}。对于整型值,可以使用 NumberInt(4字节符号整数)或NumberLong(8字节符号整数), {“x”:NumberInt(“3”)}{“x”:NumberLong(“3”)}
  • 字符串:UTF-8字符串都可以表示为字符串类型的数据{“x”:“你好”}
  • 日期:日期被存储为自新纪元依赖经过的毫秒数,不存储时区,{“x”:new Date()}
  • 正则表达式:查询时,使用正则表达式作为限定条件,语法与JavaScript的正则表达式相同{“x”😕[abc]/}
  • 数组:数据列表或数据集可以表示为数组,{“x”: [“a“,“b”,”c”]}
  • 内嵌文档:文档可以嵌套其他文档,被嵌套的文档作为值来处理,{“x”:{“y”:3 }}
  • 对象Id:对象id是一个12字节的字符串,是文档的唯一标识,{“x”: objectId() }
  • 二进制数据:二进制数据是一个任意字节的字符串。它不能直接在shell中使用。如果要 将非utf-字符保存到数据库中,二进制数据是唯一的方式。

三丶MongoDB入门

3.1 数据库以及表操作

#查看所有的数据库
> show dbs#通过use关键字切换数据库
> use admin#创建数据库
#说明:在MongoDB中,数据库是自动创建的,通过use切换到新数据库中,进行插入数据即可自动创建数据库
> use testdb> show dbs #并没有创建数据库> db.user.insert({id:1,name:'zhangsan'})  #插入数据> show dbs#查看表
> show tables> show collections#删除集合(表)
> db.user.drop()
true  #如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。#删除数据库
> use testdb #先切换到要删除的数据中> db.dropDatabase()  #删除数据库

3.2 新增数据

在MongoDB中,存储的文档结构是一种类似于json的结构,称之为bson(全称为:Binary JSON)。

#插入数据
#语法:db.表名.insert(json字符串)> db.user.insert({id:1,username:'zhangsan',age:20})> db.user.find()  #查询数据

3.3 更新数据

update() 方法用于更新已存在的文档。语法格式如下:

db.collection.update(<query>,<update>,[upsert: <boolean>,multi: <boolean>,writeConcern: <document>]
)

参数说明:

  • query : update的查询条件,类似sql update查询内where后面的。
  • update : update的对象和一些更新的操作符(如 , , ,inc.$set)等,也可以理解为sql update查询内set后面的
  • upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
  • multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
  • writeConcern :可选,抛出异常的级别。
#查询全部
> db.user.find()#更新数据
> db.user.update({id:1},{$set:{age:22}}) #注意:如果这样写,会删除掉其他的字段
> db.user.update({id:1},{age:25})#更新不存在的字段,会新增字段
> db.user.update({id:2},{$set:{sex:1}}) #更新数据#更新不存在的数据,默认不会新增数据
> db.user.update({id:3},{$set:{sex:1}})#如果设置第一个参数为true,就是新增数据
> db.user.update({id:3},{$set:{sex:1}},true)

3.4 删除数据

通过remove()方法进行删除数据,语法如下:

db.collection.remove(<query>,{justOne: <boolean>,writeConcern: <document>}
)

参数说明:

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

实例:

#删除数据
> db.user.remove({})#插入4条测试数据
db.user.insert({id:1,username:'zhangsan',age:20})
db.user.insert({id:2,username:'lisi',age:21})
db.user.insert({id:3,username:'wangwu',age:22})
db.user.insert({id:4,username:'zhaoliu',age:22})> db.user.remove({age:22},true)#删除所有数据
> db.user.remove({})

3.5 查询数据

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

db.user.find([query],[fields])
  • query :可选,使用查询操作符指定查询条件
  • fields :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。

条件查询:

操作格式范例RDBMS中的类似语句
等于{<key>:<value>}db.col.find({"by":"黑马程序员"}).pretty()where by = '黑马程序员'
小于{<key>:{$lt:<value>}}db.col.find({"likes":{$lt:50}}).pretty()where likes < 50
小于或等于{<key>:{$lte:<value>}}db.col.find({"likes":{$lte:50}}).pretty()where likes <= 50
大于{<key>:{$gt:<value>}}db.col.find({"likes":{$gt:50}}).pretty()where likes > 50
大于或等于{<key>:{$gte:<value>}}db.col.find({"likes":{$gte:50}}).pretty()where likes >= 50
不等于{<key>:{$ne:<value>}}db.col.find({"likes":{$ne:50}}).pretty()where likes != 50

实例:

#插入测试数据
db.user.insert({id:1,username:'zhangsan',age:20})
db.user.insert({id:2,username:'lisi',age:21})
db.user.insert({id:3,username:'wangwu',age:22})
db.user.insert({id:4,username:'zhaoliu',age:22})db.user.find()  #查询全部数据
db.user.find({},{id:1,username:1})  #只查询id与username字段
db.user.find().count()  #查询数据条数
db.user.find({id:1}) #查询id为1的数据
db.user.find({age:{$lte:21}}) #查询小于等于21的数据
db.user.find({$or:[{id:1},{id:2}]}) #查询id=1 or id=2#分页查询:Skip()跳过几条,limit()查询条数
db.user.find().limit(2).skip(1)  #跳过1条数据,查询2条数据
db.user.find().sort({id:-1}) #按照id倒序排序,-1为倒序,1为正序

3.6 索引

索引通常能够极大的提高查询的效率,如果没有索引MongoDB在读取数据时必须草棉集合中的每个文件选取那些符合查询条件的记录
这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。
索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构

#创建索引
> db.user.createIndex({'age':1})#查看索引
> db.user.getIndexes()
[{"v" : 2,"key" : {"_id" : 1},"name" : "_id_","ns" : "testdb.user"}
]
#说明:1表示升序创建索引,-1表示降序创建索引。

3.7 执行计划

MongoDB查询分析可以确保我们建议的索引有效,是查询语句性能分析的重要工具

#插入1000条数据
for(var i=1;i<1000;i++)db.user.insert({id:100+i,username:'name_'+i,age:10+i})#查看执行计划
> db.user.find({age:{$gt:100},id:{$lt:200}}).explain()#测试没有使用索引
> db.user.find({username:'zhangsan'}).explain()#winningPlan:最佳执行计划
#"stage" : "FETCH", #查询方式,常见的有COLLSCAN/全表扫描、IXSCAN/索引扫描、FETCH/根据索引去检索文档、SHARD_MERGE/合并分片结果、IDHACK/针对_id进行查询

四丶SpringData-Mongo

Spring-data对MongoDB做了支持,使用spring-data-mongodb可以简化MongoDB的操作,封装了底层的mongodb-driver。

地址:https://spring.io/projects/spring-data-mongodb

使用Spring-Data-MongoDB很简单,只需要如下几步即可:

  • 导入起步依赖
  • 编写配置信息
  • 编写实体类(配置注解 @Document,@Id)
  • 操作mongodb
    • 注入MongoTemplate对象,完成CRUD操作
    • 编写Repository接口,注入接口完成基本Crud操作

4.1、环境搭建

第一步,导入依赖:

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.9.RELEASE</version>
</parent>
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>

第二步,编写application.yml配置文件

spring:data:mongodb:uri: mongodb://192.168.136.160:27017/test

第三步,编写启动类

package com.tanhua.mongo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class MongoApplication {public static void main(String[] args) {SpringApplication.run(MongoApplication.class, args);}
}

4.2、完成基本操作

第一步,编写实体类

package com.tanhua.mongo.domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.mapping.Document;@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(value="person")
public class Person {private ObjectId id;private String name;private int age;private String address;}

第二步,通过MongoTemplate完成CRUD操作

package cn.itcast.mongo.test;import cn.itcast.mongo.MongoApplication;
import cn.itcast.mongo.domain.Person;
import org.bson.types.ObjectId;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.test.context.junit4.SpringRunner;import java.util.List;@RunWith(SpringRunner.class)
@SpringBootTest(classes = MongoApplication.class)
public class MongoTest {/*** SpringData-mongodb操作*    1、配置实体类*    2、实体类上配置注解(配置集合和对象间的映射关系)*    3、注入MongoTemplate对象*    4、调用对象方法,完成数据库操作*/@Autowiredprivate MongoTemplate mongoTemplate;//保存@Testpublic void testSave() {for (int i = 0; i < 10; i++) {Person person = new Person();person.setId(ObjectId.get()); //ObjectId.get():获取一个唯一主键字符串person.setName("张三"+i);person.setAddress("北京顺义"+i);person.setAge(18+i);mongoTemplate.save(person);}}//查询-查询所有@Testpublic void testFindAll() {List<Person> list = mongoTemplate.findAll(Person.class);for (Person person : list) {System.out.println(person);}}@Testpublic void testFind() {//查询年龄小于20的所有人Query query = new Query(Criteria.where("age").lt(20)); //查询条件对象//查询List<Person> list = mongoTemplate.find(query, Person.class);for (Person person : list) {System.out.println(person);}}/*** 分页查询*/@Testpublic void testPage() {Criteria criteria = Criteria.where("age").lt(30);//1、查询总数Query queryCount = new Query(criteria);long count = mongoTemplate.count(queryCount, Person.class);System.out.println(count);//2、查询当前页的数据列表, 查询第二页,每页查询2条Query queryLimit = new Query(criteria).limit(2)//设置每页查询条数.skip(2) ; //开启查询的条数 (page-1)*sizeList<Person> list = mongoTemplate.find(queryLimit, Person.class);for (Person person : list) {System.out.println(person);}}/*** 更新:*    根据id,更新年龄*/@Testpublic void testUpdate() {//1、条件Query query = Query.query(Criteria.where("id").is("5fe404c26a787e3b50d8d5ad"));//2、更新的数据Update update = new Update();update.set("age", 20);mongoTemplate.updateFirst(query, update, Person.class);}@Testpublic void testRemove() {Query query = Query.query(Criteria.where("id").is("5fe404c26a787e3b50d8d5ad"));mongoTemplate.remove(query, Person.class);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/web/82788.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt学习及使用_第1部分_认识Qt---Qt简介

前言 学以致用,通过QT框架的学习,一边实践,一边探索编程的方方面面. 参考书:<Qt 6 C开发指南>(以下称"本书") 标识说明:概念用粗体倾斜.重点内容用(加粗黑体)---重点内容(红字)---重点内容(加粗红字), 本书原话内容用深蓝色标识,比较重要的内容用加粗倾斜下划线…

Python语法基础篇(包含类型转换、拷贝、可变对象/不可变对象,函数,拆包,异常,模块,闭包,装饰器)

Python语法基础篇&#xff08;二&#xff09; 类型转换拷贝可变对象与不可变对象可变对象不可变对象 函数拆包异常模块闭包装饰器 &#x1f439;&#x1f439;&#x1f439;&#x1f439;&#x1f439;一只正在努力学习计算机技术的小仓鼠&#xff0c;尾部有课程链接哦~&#x…

录制mp4

目录 单线程保存mp4 多线程保存mp4 rtsp ffmpeg录制mp4 单线程保存mp4 import cv2 import imageiocv2.namedWindow(photo, 0) # 0窗口大小可以任意拖动&#xff0c;1自适应 cv2.resizeWindow(photo, 1280, 720) url "rtsp://admin:aa123456192.168.1.64/h264/ch1/main…

ISBN书号查询接口如何用PHP实现调用?

一、什么是ISBN书号查询接口 ISBN数据查询接口是一项图书信息查询服务。它基于全球通用的ISBN编码系统&#xff0c;帮助用户快速获取图书的详细信息&#xff0c;包括书名、作者、出版社、出版时间、价格、封面等关键字段。 该接口广泛应用于电商平台、图书馆管理系统、二手书…

Redis底层数据结构之深入理解跳表(2)

上一篇文章中我们详细讲述了跳表的增添、查找和修改的操作&#xff0c;这篇文章我们来讲解一下跳表在多线程并发时的安全问题。在Redis中&#xff0c;除了网络IO部分和大文件的后台复制涉及到多线程外&#xff0c;其余任务执行时全部都是单线程&#xff0c;这也就意味着在Redis…

Go语言依赖管理与版本控制-《Go语言实战指南》

在现代软件开发中&#xff0c;项目的第三方依赖和版本控制扮演着至关重要的角色。Go 语言自 Go 1.11 引入 Modules&#xff08;模块化管理&#xff09;以来&#xff0c;已经实现了内建的依赖管理机制&#xff0c;彻底摆脱了传统 GOPATH 模式的限制。 本章将深入探讨如何使用 Go…

Appium+python自动化(十一)- 元素定位- 下

1、 List定位 List顾名思义就是一个列表&#xff0c;在python里面也有list这一个说法&#xff0c;如果你不是很理解什么是list&#xff0c;这里暂且理解为一个数组或者说一个集合。首先一个list是一个集合&#xff0c;那么他的个数也就成了不确定性&#xff0c;所以这里需要用复…

stress 服务器压力测试的工具学习

一、stress 工具介绍 tress 是一种工具&#xff0c;可以对符合 POSIX 标准的操作系统施加可配置数量的 CPU、内存、I/O 或磁盘压力&#xff0c;并报告其检测到的任何错误。 stress 不是一个基准测试。它是由系统管理员用来评估其系统扩展性的工具&#xff0c;由内核程序员用来…

不止抓请求:5种开发场景中的抓包组合策略(含 Charles 等工具)

很多开发者用抓包&#xff0c;只在“接口调不通”的时候。 但在复杂项目中&#xff0c;抓包早已不仅是调错工具&#xff0c;更是开发节奏提速器、协作问题解耦器、架构瓶颈探测器。 关键在于——不同场景下&#xff0c;你要用对方法、配对工具。 以下是我根据日常开发实战&a…

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…

计算机系统大作业——程序人生

计算机系统 大作业 题 目 程序人生-Hello’s P2P 专 业 物联网工程 学   号 2022112820 班 级 2237301 学 生 孟宇航 指 导 教 师 吴 锐 计算机科学与技术学院 2024年…

〈软件安装管家软件目录〉▷Windows系统版

①装机常用 ☞压缩解压WinRAR7-ZIPBandZip360压缩☞文件工具EverythingOneCommander XYplorer ReNamer ☞卸载软件CCleanerIObitUninstallerUninstall toolGeekAutodesk卸载Adobe卸载Ashampoo☞驱动软件驱动人生&#xff08;离线版&#xff09;驱动精灵&#xff08;离线版&…

CentOS Stream 8 Unit network.service not found

一、问题现象 在 CentOS Stream 8 操作系统中&#xff0c;配置完静态IP 信息&#xff0c;想重启网络服务。 执行如下命令&#xff1a; systemctl restart network 提示信息如下&#xff1a; Failed to restart network.service: Unit network.service not found. 二、问题…

极空间z4pro配置gitea mysql,内网穿透

极空间z4pro配置gitea mysql等记录&#xff0c;内网穿透 1、mysql、gitea镜像下载&#xff0c;极空间不成功&#xff0c;先用自己电脑科学后下载镜像,拉取代码&#xff1a; docker pull --platform linux/amd64 gitea/gitea:1.23 docker pull --platform linux/amd64 mysql:5.…

[假面骑士] 龙骑浅谈

作为一个伪二次元的我&#xff0c;总感觉目前没有什么好番可追。结果某一天在小破站刷到了一个假面骑士相关的视频&#xff0c;我就突发奇想&#xff0c;要不把假面骑士补完算了。 搜了搜&#xff0c;版权全在企鹅哪儿&#xff0c;不想充&#xff0c;于是去找了某盘的资源。果…

F5 GSLB 最佳实践:如何手动将Wide IP 故障转移到另一个数据中心

下面简要介绍如何手动将 Wide IP(用于 DNS 负载均衡)故障转移到另一个数据中心,并提供一些最佳实践。假设您使用 F5 BIG-IP DNS(以前称为 GTM)管理一个 Wide IP,该 IP 引用位于不同数据中心的虚拟服务器 (VIP)。 典型的 GSLB (BIG-IP DNS) 设置 Wide IP:表示您想要全局负…

FART 脱壳某大厂 App + CodeItem 修复 dex + 反编译还原源码

版权归作者所有&#xff0c;如有转发&#xff0c;请注明文章出处&#xff1a;https://cyrus-studio.github.io/blog/ FART 脱壳 fartthread 方法在 app 启动的时候&#xff08;ActivityThread&#xff09;开启 fart 线程&#xff0c;休眠 60 秒&#xff0c;等待 app 启动完成后…

在maven项目中 继续增加maven 项目

背景项目 基于若依项目 由于若依项目都是Maven项目有父子结构因此自己建项目 也需如此管理 添加子Maven项目 利用idea 自带工具 maven archetype 这里选 webapp 骨架 在这里构建自己的项目架子即可 将 这个架子加入到启动类中

网络攻防技术十四:入侵检测与网络欺骗

文章目录 一、入侵检测概述二、入侵系统的分类三、入侵检测的分析方法1、特征检测&#xff08;滥用检测、误用检测&#xff09;2、异常检测 四、Snort入侵检测系统五、网络欺诈技术1、蜜罐2、蜜网3、网络欺骗防御 六、简答题1. 入侵检测系统对防火墙的安全弥补作用主要体现在哪…

吴恩达MCP课程(5):mcp_chatbot_prompt_resource.py

前提条件&#xff1a; 1、吴恩达MCP课程&#xff08;5&#xff09;&#xff1a;research_server_prompt_resource.py 2、server_config_prompt_resource.json文件 {"mcpServers": {"filesystem": {"command": "npx","args"…