介绍
MongoDB 是一个跨平台的,面向文档的数据库,是当前 NoSQL 数据库产品中最热门
的一种。
-
MongoDB在2007开发一款分布式文档数据库,由C++编写的
-
和传统的关系型数据库相比,更加简单,结构 key-value结构
-
MySQL数据库:数据库-表-记录
MongoDB :数据库-集合-文档(记录)
-
文档类似于JSON对象,结构称为BSON
使用mongodb的原因
- 数据量大
- 写入操作频繁
- 价值较低
对于这样的数据,更适合用MongoDB来实现数据的存储。
例如吐槽和评论。
MongoDB适用场景
MongoDB不需要去明确指定一张表的具体结构,对字段的管理非常灵活,有很强的可扩展性。
支持高并发、高可用、高可扩展性,自带数据压缩功能,支持海量数据的高效存储和访问。
支持基本的CRUD、数据聚合、文本搜索和地理空间查询功能。
适用场景:
- 网站数据:Mongo非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
- 高伸缩性的场景:Mongo非常适合由数十或数百台服务器组成的数据库。
- 大尺寸,低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员往往会选择传统的文件进行存储。
- 缓存:由于性能很高,Mongo也适合作为信息基础设施的缓存层。在系统重启之后,由Mongo搭建的持久化缓存层可以避免下层的数据源过载。
例如:
弹幕、直播间互动信息、朋友圈信息、物流场景等
不适用场合:
- 高度事务性系统:例如银行系统。传统的关系型数据库目前还是更适用于需要大量原子性复杂事务的应用程序。
- 传统的商业智能应用:针对特定问题的BI数据库会对产生高度优化的查询方式。对于此类应用,数据仓库可能是更合适的选择。
mongodb特点
MongoDB 最大的特点是他支持的查询语言
非常强大,其语法有点类似于面向对象 的查询语言
,几乎可以实现类似关系数据库单表
查询的绝大部分功能,而且还支持对数据建立索引
。
它是一个面向集合的,模式自由的文档型数据库。
mongodb体系结构
mysql – databases – table – row
mongodb – databases – collections – document
面向文档和面向数据
面向文档是带结构的
,面向数据是不带结构的(例如redis)
,
面向数据,如果想获取price,需要把整个数据
拿出来,然后java代码进行解析,来得到price,
面向文档,因为存储时是带结构的,就可以在数据库端进行解析,则可以在数据库端直接
把price取出来。
{
name:zhangsan
order:[
{
itemTitle:小米9,
price:3999
}
]
}
安装和启动
docker pull mongo:7.0.0
docker run -d --restart=always -p 27017:27017 --name mongo -v /opt/mongo/data/db:/data/db mongo:7.0.0
docker exec -it mongo mongosh
基本数据类型
-
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() } ,
如不指定
,mongodb将会设置为12字节的字符串 -
二进制数据:二进制数据是一个任意字节的字符串。它不能直接在shell中使用。如果要 将
非utf-
字符保存到数据库中,二进制数据是唯一的方式。 代码:查询和文档中可以包括任何JavaScript代码,{“x”:function(){/…/}}
基础命令
show databases
# 有则切换数据库,无则创建并切换
use 数据库名
# 有则使用,无责创建
# 不写数据库名,直接 . ,则表示当前数据库
db.数据库名.集合名
# 添加数据
db.集合名.insert({"name":"zs"})
# 指定id添加数据
db.集合名.insert({"_id":"123","name":"zs"})
# 查询所有数据
db.集合名.find()
# 查询当前数据库的集合
show collections
# 测试数据 spit为集合
db.spit.insert({_id:"1",content:"我还是没有想明白到底为啥出 错",userid:"1012",nickname:"小明",visits:NumberInt(2020)});
db.spit.insert({_id:"2",content:"加班到半夜",userid:"1013",nickname:"凯 撒",visits:NumberInt(1023)});
db.spit.insert({_id:"3",content:"手机流量超了咋 办?",userid:"1013",nickname:"凯撒",visits:NumberInt(111)});
db.spit.insert({_id:"4",content:"坚持就是胜利",userid:"1014",nickname:"诺 诺",visits:NumberInt(1223)});
# 条件查询
db.spit.find({userid:'1013'})
# 只查询第一条
db.spit.findOne({userid:'1013'})
# 只取三条结果
db.spit.findOne({userid:'1013'}).limit(3)
# 修改
# 第一个参数为修改条件,
# 可以修改,也可以添加一个字段
# 此时该文档中的 {"name":"zs"} 将被删除
db.spit.update({"name":"zs"},{"age":24})
# 更新且不删除条件字段
db.spit.update({"name":"zs"},{$set:{"age":24}})
# 删除
# 删除全部
db.spit.remove()
db.spit.remove({})
# 统计数据的条数
db.spit.count()
# 模糊查询,mongodb的模糊查询是依靠正则表达式
# 以什么开头 ^ 以什么结尾$
db.spit.find({"nickname":/凯/})
# 大于 $gt 小于 $lt 大于等于 $gte 不等于$ne
db.spit.find({"vistis":{$gt:1000}})
# 包含 $in 不包含 $nin
db.spit.find({"userid":$in{"1012":"1000"}})
# 条件连接符 and or
db.spit.find({$and:[ {visits:{$gte:1000}} ,{visits:{$lt:2000} }]})
db.spit.find({$or:[ {userid:"1013"} ,{visits:{$lt:2000} }]})
# 列值增长
# 在原有基础上增加或减少,正数为加一,负数为减一
db.spit.update({_id:"2"},{$inc:{visits:NumberInt(1)}} )
# 按条件筛选,并排序,
# 排序 1为升序,-1为降序
# 查询索引为10,共10条数据
db.集合名.find({},{"title":1,_id:0}).sort({"likes":-1}).skip(10).limit(10)
java操作mongodb
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver</artifactId>
</dependency>
package test;
import com.mongodb.BasicDBObject;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.tensquare.gathering.GatheringApplication;
import org.bson.Document;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.HashMap;
import java.util.Map;
@SpringBootTest(classes = GatheringApplication.class)
@RunWith(SpringRunner.class)
public class MongodbTest {
@Test
public void testMongo(){
// 创建mongodb的客户端
MongoClient mongoClient = new MongoClient("192.168.190.0");
// 1.选择数据库 spitdb use spitdb
MongoDatabase testdatabase = mongoClient.getDatabase("testdatabase");
// 2.获取spit集合
MongoCollection<Document> spitCollection = testdatabase.getCollection("spit");
// 构建查询的条件
BasicDBObject basicDBObject = new BasicDBObject("userid", "1013");
// 3.使用集合执行find()查询操作
FindIterable<Document> documents = spitCollection.find(basicDBObject);
// 4.展示查询到的数据
for (Document document : documents) {
System.out.println(document.get("_id"));
}
}
@Test
public void insertMongo(){
// 创建mongodb的客户端
MongoClient mongoClient = new MongoClient("192.168.190.0");
// 1.选择数据库 spitdb use spitdb
MongoDatabase testdatabase = mongoClient.getDatabase("testdatabase");
// 2.获取spit集合
MongoCollection<Document> spitCollection = testdatabase.getCollection("spit");
Map<String,Object> map = new HashMap<>();
map.put("_id","5");
map.put("nickname","5");
Document document = new Document(map);
spitCollection.insertOne(document);
}
}
springdataMongo
接口
package com.tensquare.spit.dao;
import com.tensquare.spit.pojo.Spit;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.repository.MongoRepository;
//使用SpringDataMongodb,用法和SpringDataJpa类似
//编写Dao的时候,需要继承xxxRepository
public interface SpitDao extends MongoRepository<Spit, String> {
//之前使用SpringDataJpa的查询方式,五种
//1. 使用JpaRepository的接口方法
//2. 通过对查询方法名命名的方式 findByIshot()
//3. 使用jpql查询语句 @Query注解
//4. 使用sql语句(推荐) @Query注解
//5. 使用Specification进行复杂的条件查询
//本例中使用2,方法名命名的方式实现
//根据上级id (parentid) 分页查询吐槽数据
Page<Spit> findByParentid(String parentId, Pageable pageable);
}
service
Spit spit = spitDao.findById(spitId).get();
List<Spit> list = spitDao.findAll();
spitDao.save(spit);
spitDao.deleteById(spitId);
mongodbTemplate
实现点赞功能
service
package com.tensquare.spit.service;
import com.tensquare.spit.dao.SpitDao;
import com.tensquare.spit.pojo.Spit;
import org.springframework.beans.factory.annotation.Autowired;
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.stereotype.Service;
import util.IdWorker;
import java.util.List;
@Service
public class SpitService {
@Autowired
private MongoTemplate mongoTemplate;
public void thumbup(String spitId) {
// 构建更新条件
Query query = new Query();
query.addCriteria(Criteria.where("_id").is(spitId));
// 构建更新数据
// 列值增长
Update update = new Update();
update.inc("thumbup",1);
//方法是进行修改
//第一个参数:设置修改数据的条件
//第二个参数:设置修改成什么样的数据
//第三个参数:设置集合名字
mongoTemplate.updateFirst(query,update,"spit");
}
}
controller
@PutMapping("thumbup/{spitId}")
public Result thumbup(@PathVariable String spitId){
// 解决重复点赞的问题,一般一个用户只能点赞一次
// 当用户进行点赞之后可以记录用户的点赞操作,用户id + 吐槽id
// 这个数据可以放到redis,redis的特点快,不适合放太大的数据(最起码上千万)
// todo 假设已经获取到了用户id
String userId = "1013";
Object result = redisTemplate.opsForValue().get("thumbup_" + userId + "_" + spitId);
if (result!=null){
return new Result(false,StatusCode.REPEERROR,"不能重复点赞");
}
redisTemplate.opsForValue().set("thumbup_" + userId + "_" + spitId,1);
spitService.thumbup(spitId);
return new Result(true,StatusCode.OK,"点赞成功");
}
springboot整合mongodb
todo 有时间再和上面的整合一下吧
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.atguigu</groupId>
<artifactId>mongo_demo01</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mongodb-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
spring:
data:
mongodb:
database: daijia
host: 192.168.2.129
port: 27017
@Data
@Document("user") //指定mongodb中的集合名字
public class User {
@Id
private ObjectId id;
private String name;
private Integer age;
private String email;
private Date createDate;
}
MongoRepository
public interface UserRepository extends MongoRepository<User, ObjectId> {
}
@SpringBootTest
public class MongoRepositoryTest {
@Autowired
private UserRepository userRepository;
//添加
@Test
public void add() {
User user = new User();
user.setName("mary");
user.setAge(30);
user.setCreateDate(new Date());
userRepository.save(user);
}
//查询所有
@Test
public void findAll() {
List<User> list = userRepository.findAll();
System.out.println(list);
}
//根据id查询
@Test
public void testFindById() {
Optional<User> optional =
userRepository.findById(new ObjectId("666a9a85f5294513720647ff"));
boolean present = optional.isPresent();
if(present) {
User user = optional.get();
System.out.println(user);
}
}
//条件查询 + 排序
// age = 20
@Test
public void testFindCondition() {
//封装条件
User user = new User();
user.setAge(20);
Example<User> example = Example.of(user);
Sort sort = Sort.by(Sort.Direction.DESC, "name");
List<User> list = userRepository.findAll(example, sort);
System.out.println(list);
}
//条件查询 + 排序
// age = 20
@Test
public void testFindCondition() {
//封装条件
User user = new User();
user.setAge(20);
Example<User> example = Example.of(user);
Sort sort = Sort.by(Sort.Direction.DESC, "name");
List<User> list = userRepository.findAll(example, sort);
System.out.println(list);
}
//分页查询
@Test
public void testPage() {
//第一页从0开始的
PageRequest pageable = PageRequest.of(0,2);
Page<User> page = userRepository.findAll(pageable);
List<User> list = page.getContent();
System.out.println(list);
}
//更新
@Test
public void testUpdateUser(){
//注意:先查询,再更新
Optional<User> optional = userRepository.findById(
new ObjectId("64eee9dff317c823c62b4faf")
);
if(optional.isPresent()){
User user = optional.get();
user.setAge(100);
//user中包含id,就会执行更新
userRepository.save(user);
System.out.println(user);
}
}
//删除
@Test
public void testDeleteUser(){
userRepository.deleteById(
new ObjectId("64eee9dff317c823c62b4faf")
);
}
}
MongoTemplate
@SpringBootTest
public class MongoTemplateTest {
@Autowired
private MongoTemplate mongoTemplate;
//添加
@Test
public void add() {
User user = new User();
user.setName("test");
user.setAge(20);
user.setCreateDate(new Date());
mongoTemplate.insert(user);
}
//查询所有
@Test
public void findAll() {
List<User> list = mongoTemplate.findAll(User.class);
list.forEach(user->{
System.out.println(user);
});
}
//根据id查询
@Test
public void testFindId() {
User user = mongoTemplate.findById("666a9b5e9a3653796627bb3c", User.class);
System.out.println(user);
}
//条件查询
@Test
public void testCondition() {
// where name=? and age=?
Criteria criteria =
Criteria.where("name").is("test").and("age").is(20);
Query query = new Query(criteria);
List<User> list = mongoTemplate.find(query,User.class);
System.out.println(list);
}
//分页查询
@Test
public void testPage() {
// limit 0,2
Query query = new Query();
List<User> list = mongoTemplate.find(query.skip(0).limit(2), User.class);
list.forEach(user->{
System.out.println(user);
});
}
//修改和删除
//修改
@Test
public void testUpdateUser() {
Criteria criteria = Criteria.where("_id").is("64eeeae31711344f35635788");
Query query = new Query(criteria);
Update update = new Update();
update.set("name", "zhangsan");
update.set("age", 99);
UpdateResult result = mongoTemplate.upsert(query, update, User.class);//改一条
//UpdateResult result = mongoTemplate.updateMulti(query, update, User.class);//改多条
long count = result.getModifiedCount();
System.out.println(count);
}
//删除
@Test
public void testRemove() {
Criteria criteria = Criteria.where("_id").is("64eeeae31711344f35635788");
Query query = new Query(criteria);
DeleteResult result = mongoTemplate.remove(query, User.class);
long count = result.getDeletedCount();
System.out.println(count);
}
}
陈玉下定决心带妈妈去看医生。很快,刘丹在宣武医院确诊为阿尔茨海默症。陈玉终于知道,妈妈的无端发怒、对外界的隔阂、对亲人的不理解,都是有原因的。她病了。
https://new.qq.com/omn/20220329/20220329A0AQ0000.html?pgv_ref=aio2015&ptlang=2052