1.什么是 MongoDB
MongoDB:是一个数据库 ,高性能、无模式、文档性,目前 nosql 中最热门的数据库,开源产品,基于 c++开发。是 nosql 数据库中功能最丰富,最像关系数据库的。
特性 :
面向集合文档的存储:适合存储 Bson(json 的扩展)形式的数据;
格式自由,数据格式不固定,生产环境下修改结构都可以不影响程序运行;
强大的查询语句,面向对象的查询语言,基本覆盖 sql 语言所有能力;
完整的索引支持,支持查询计划;
支持复制和自动故障转移;
支持二进制数据及大型对象(文件)的高效存储;
使用分片集群提升系统扩展性;
使用内存映射存储引擎,把磁盘的 IO 操作转换成为内存的操作;
2.什么情况下可以使用 MongoDB
3.MongoDB 使用场景
MongoDB 的应用已经渗透到各个领域,比如游戏、物流、电商、内容管理、社交、物联网、视频直播等,以下是几个实际的应用案例:
游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新
物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。
社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能
物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析
视频直播,使用 MongoDB 存储用户信息、礼物信息等
4.不推荐使用 MongoDB 的场景
高度事务性系统:例如银行、财务等系统。MongoDB 对事物的支持较弱;
传统的商业智能应用:特定问题的数据分析,多数据实体关联,涉及到复杂的、高度优化的查询方式;
使用 sql 方便的时候:数据结构相对固定,使用 sql 进行查询统计更加便利的时候;
5.安装
6.推荐连接工具
Navicat Premium 12
7.使用
1.新增5人
db.users.drop();
var user1 = { "username" : "lison", "country" : "china", "address" : { "aCode" : "411000", "add" : "长沙"
},"favorites" : { "movies" : ["杀破狼 2","战狼","雷神 1"], "cites" : ["长沙","深圳","上海"]
},"age" : 18, "salary":NumberDecimal("18889.09"), "lenght" :1.79
};
var user2 = { "username" : "james", "country" : "English", "address" : { "aCode" : "311000", "add" : "地址"
},"favorites" : {
"movies" : ["复仇者联盟","战狼","雷神 1"], "cites" : ["西安","东京","上海"]
},"age" : 24, "salary":NumberDecimal("7889.09"), "lenght" :1.35
};
var user3 ={ "username" : "deer", "country" : "japan", "address" : { "aCode" : "411000", "add" : "长沙"
},"favorites" : { "movies" : ["肉蒲团","一路向西","倩女幽魂"], "cites" : ["东莞","深圳","东京"]
},"age" : 22, "salary":NumberDecimal("6666.66"), "lenght" :1.85
};
var user4 =
{ "username" : "mark", "country" : "USA", "address" : { "aCode" : "411000", "add" : "长沙"
},"favorites" : { "movies" : ["蜘蛛侠","钢铁侠","蝙蝠侠"], "cites" : ["青岛","东莞","上海"]
},"age" : 20, "salary":NumberDecimal("6398.22"), "lenght" :1.77
};
var user5 =
{ "username" : "peter", "country" : "UK", "address" : {
"aCode" : "411000", "add" : "TEST"
},"favorites" : { "movies" : ["蜘蛛侠","钢铁侠","蝙蝠侠"], "cites" : ["青岛","东莞","上海"]
}, "salary":NumberDecimal("1969.88")
};
db.users.insert(user1);
db.users.insert(user2);
db.users.insert(user3);
db.users.insert(user4);
db.users.insert(user5);
2.查询
查询喜欢的城市包含东莞和东京的 user
db.users.find({ "favorites.cites" : { "$all" : [ "东莞" , "东京"]}}).pretty()
查询国籍为英国或者美国,名字中包含 s 的 user
db.users.find({ "$and" : [ { "username" : { "$regex" : ".*s.*"}} , { "$or" : [ { "country" : "English"} , { "country" : "USA"}]}]}).pretty()
3.修改
把 lison 的年龄修改为 6 岁
db.users.updateMany({ "username" : "lison"},{ "$set" : { "age" : 6}})
喜欢的城市包含东莞的人,给他喜欢的电影加入"小电影 2""小电影 3"
db.users.updateMany({ "favorites.cites" : " 东 莞 "}, { "$addToSet" : { "favorites.movies" :{ "$each" : [ "小电影 2 " , "小电影 3"]}}},true)
4.删除
删除名字为 lison 的 user
db.users.deleteMany({ "username" : "lison"} )
删除年龄大于 8 小于 25 的 user
db.users.deleteMany({"$and" : [ {"age" : {"$gt": 8}} , {"age" : {"$lt" : 25}}]})
8.java代码整合MongoDB
引入 pom 文件
<dependencies>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.11.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
Document 方式
package cn.enjoy.mg;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.junit.Before;
import org.junit.Test;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import static com.mongodb.client.model.Updates.*;
import static com.mongodb.client.model.Filters.*;
//原生 java 驱动 document 的操作方式
public class QuickStartJavaDocTest {
//数据库
private MongoDatabase db;
//文档集合
private MongoCollection<Document> doc;
//连接客户端(内置连接池)
private MongoClient client;
@Before
public void init() {
client = new MongoClient("192.168.244.123", 27017);
db = client.getDatabase("lison");
doc = db.getCollection("users");
}
@Test
public void insertDemo() {
Document doc1 = new Document();
doc1.append("username", "cang");
doc1.append("country", "USA");
doc1.append("age", 20);
doc1.append("lenght", 1.77f);
doc1.append("salary", new BigDecimal("6565.22"));//存金额,使用bigdecimal 这个数据类型
//添加“address”子文档
Map<String, String> address1 = new HashMap<String, String>();
address1.put("aCode", "0000");
address1.put("add", "xxx000");
doc1.append("address", address1);
//添加“favorites”子文档,其中两个属性是数组
Map<String, Object> favorites1 = new HashMap<String, Object>();
favorites1.put("movies", Arrays.asList("aa", "bb"));
favorites1.put("cites", Arrays.asList("东莞", "东京"));
doc1.append("favorites", favorites1);
Document doc2 = new Document();
doc2.append("username", "Chen");
doc2.append("country", "China");
doc2.append("age", 30);
doc2.append("lenght", 1.77f);
doc2.append("salary", new BigDecimal("8888.22"));
Map<String, String> address2 = new HashMap<>();
address2.put("aCode", "411000");
address2.put("add", "我的地址 2");
doc2.append("address", address2);
Map<String, Object> favorites2 = new HashMap<>();
favorites2.put("movies", Arrays.asList("东游记", "一路向东"));
favorites2.put("cites", Arrays.asList("珠海", "东京"));
doc2.append("favorites", favorites2);
//使用 insertMany 插入多条数据
doc.insertMany(Arrays.asList(doc1, doc2));
}
@Test
public void testFind() {
final List<Document> ret = new ArrayList<>();
//block 接口专门用于处理查询出来的数据
Consumer<Document> printDocument = new Consumer<Document>() {
@Override
public void accept(Document document) {
System.out.println(document);
ret.add(document);
}
};
//select * from users where favorites.cites has "东莞"、"东京"
//db.users.find({ "favorites.cites" : { "$all" : [ "东莞" , "东京"]}})
Bson all = all("favorites.cites", Arrays.asList("东莞", "东京"));//定义数据过滤器,喜欢的城市中要包含"东莞"、"东京" FindIterable<Document> find = doc.find(all);
find.forEach(printDocument);
System.out.println("------------------>" + String.valueOf(ret.size()));
ret.removeAll(ret);
//select * from users where username like '%s%' and (contry= English or contry =USA)
// db.users.find({ "$and" : [ { "username" : { "$regex" : ".*c.*"}} , { "$or" : [ { "country" : "English"} , { "country" : "USA"}]}]})
String regexStr = ".*c.*";
Bson regex = regex("username", regexStr);//定义数据过滤器,username like '%s%' Bson or = or(eq("country", "English"), eq("country", "USA"));// 定义数据过滤器,(contry= English or contry = USA)
Bson and = and(regex, or);
FindIterable<Document> find2 = doc.find(and);
find2.forEach(printDocument);
System.out.println("------------------>" + String.valueOf(ret.size()));
}
@Test
public void testUpdate() {
//update users set age=6 where username = 'lison' // db.users.updateMany({ "username" : "lison"},{ "$set" : { "age" : 6}},true)
Bson eq = eq("username", "cang");//定义数据过滤器,username = 'cang' Bson set = set("age", 8);//更新的字段.来自于 Updates 包的静态导入UpdateResult updateMany = doc.updateMany(eq, set);
System.out.println("------------------>" +String.valueOf(updateMany.getModifiedCount()));//打印受影响的行数
//update users set favorites.movies add "小电影 2 ", "小电影3" where favorites.cites
has "东莞"
//db.users.updateMany({ "favorites.cites" : " 东 莞 "}, { "$addToSet" :
{ "favorites.movies" : { "$each" : [ "小电影 2 " , "小电影 3"]}}},true)
Bson eq2 = eq("favorites.cites", "东莞");//定义数据过滤器,favorites.cites has "东莞" Bson addEachToSet = addEachToSet("favorites.movies", Arrays.asList("小电影2 ", "小电影 3"));//更新的字段.来自于 Updates 包的静态导入
UpdateResult updateMany2 = doc.updateMany(eq2, addEachToSet);
System.out.println("------------------>" +String.valueOf(updateMany2.getModifiedCount()));
}
@Test
public void testDelete() {
//delete from users where username = ‘lison’ //db.users.deleteMany({ "username" : "lison"} )
Bson eq = eq("username", "lison");//定义数据过滤器,username='lison' DeleteResult deleteMany = doc.deleteMany(eq);
System.out.println("------------------>" +String.valueOf(deleteMany.getDeletedCount()));//打印受影响的行数
//delete from users where age >8 and age <25
//db.users.deleteMany({"$and" : [ {"age" : {"$gt": 8}} , {"age" : {"$lt" : 25}}]})
Bson gt = gt("age", 8);//定义数据过滤器,age > 8,所有过滤器的定义来自于Filter
这个包的静态方法,需要频繁使用所以静态导入
// Bson gt = Filter.gt("age",8);
Bson lt = lt("age", 25);//定义数据过滤器,age < 25
Bson and = and(gt, lt);//定义数据过滤器,将条件用 and 拼接DeleteResult deleteMany2 = doc.deleteMany(and);
System.out.println("------------------>" +String.valueOf(deleteMany2.getDeletedCount()));//打印受影响的行数
}
@Test
public void testTransaction() {
// begin
// update users set lenght= lenght-1 where username = ‘james’ // update users set lenght= lenght+1 where username = ‘lison’ // commit
ClientSession clientSession = client.startSession();
clientSession.startTransaction();
Bson eq = eq("username", "james");
Bson inc = inc("lenght", -1);
doc.updateOne(clientSession,eq,inc);
Bson eq2 = eq("username", "lison");
Bson inc2 = inc("lenght", 1);
doc.updateOne(clientSession,eq2,inc2);
clientSession.commitTransaction();
// clientSession.abortTransaction();
}
}
POJO 方式(不建议使用)
新增 Favorites
package cn.enjoy.entity;
import java.util.List;
public class Favorites {
private List<String> movies;
private List<String> cites;
public List<String> getMovies() {
return movies;
}
public void setMovies(List<String> movies) {
this.movies = movies;
}
public List<String> getCites() {
return cites;
}
public void setCites(List<String> cites) {
this.cites = cites;
}
@Override
public String toString() {
return "Favorites [movies=" + movies + ", cites=" + cites + "]";
}
}
新增 Address
package cn.enjoy.entity;
public class Address {
private String aCode;
private String add;
public String getaCode() {
return aCode;
}
public void setaCode(String aCode) {
this.aCode = aCode;
}
public String getAdd() {
return add;
}
public void setAdd(String add) {
this.add = add;
}
@Override
public String toString() {
return "Address [aCode=" + aCode + ", add=" + add + "]";
}
}
新增 User
package cn.enjoy.entity;
import java.math.BigDecimal;
import org.bson.types.ObjectId;
public class User {
private ObjectId id;
private String username;
private String country;
private Address address;
private Favorites favorites;
private int age;
private BigDecimal salary;
private float lenght;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Favorites getFavorites() {
return favorites;
}
public void setFavorites(Favorites favorites) {
this.favorites = favorites;
}
public ObjectId getId() {
return id;
}
public void setId(ObjectId id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public BigDecimal getSalary() {
return salary;
}
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
public float getLenght() {
return lenght;
}
public void setLenght(float lenght) {
this.lenght = lenght;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", country=" + country + ", address=" + address + ", favorites=" + favorites
+ ", age=" + age + ", salary=" + salary + ", lenght=" + lenght +"]";
}
}
使用
package cn.enjoy.mg;
import static com.mongodb.client.model.Updates.*;
import static com.mongodb.client.model.Filters.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import org.bson.Document;
import org.bson.codecs.configuration.CodecRegistries;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.codecs.pojo.PojoCodecProvider;
import org.bson.conversions.Bson;
import org.junit.Before;
import org.junit.Test;
import cn.enjoy.entity.Address;
import cn.enjoy.entity.Favorites;
import cn.enjoy.entity.User;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.ServerAddress;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Updates;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
//原生 java 驱动 Pojo 的操作方式
public class QuickStartJavaPojoTest {
private MongoDatabase db;
private MongoCollection<User> doc;
private MongoClient client;
@Before
public void init(){
//编解码器的 list
List<CodecRegistry> codecResgistes = new ArrayList<>();
//list 加入默认的编解码器集合
codecResgistes.add(MongoClient.getDefaultCodecRegistry());
//生成一个 pojo 的编解码器
CodecRegistry pojoCodecRegistry = CodecRegistries. fromProviders(PojoCodecProvider.builder().automatic(true).build());
//list 加入 pojo 的编解码器
codecResgistes.add(pojoCodecRegistry);
//通过编解码器的 list 生成编解码器注册中心
CodecRegistry registry = CodecRegistries.fromRegistries(codecResgistes);
//把编解码器注册中心放入 MongoClientOptions
//MongoClientOptions 相当于连接池的配置信息
MongoClientOptions build = MongoClientOptions.builder(). codecRegistry(registry).build();
ServerAddress serverAddress = new ServerAddress("192.168.244.123", 27017);
client = new MongoClient(serverAddress, build);
db =client.getDatabase("lison");
doc = db.getCollection("users",User.class);
}
@Test
public void insertDemo(){
User user = new User();
user.setUsername("cang");
user.setCountry("USA");
user.setAge(20);
user.setLenght(1.77f);
user.setSalary(new BigDecimal("6265.22"));
//添加“address”子文档
Address address1 = new Address();
address1.setaCode("411222");
address1.setAdd("sdfsdf");
user.setAddress(address1);
//添加“favorites”子文档,其中两个属性是数组
Favorites favorites1 = new Favorites();
favorites1.setCites(Arrays.asList("东莞","东京"));
favorites1.setMovies(Arrays.asList("西游记","一路向西"));
user.setFavorites(favorites1);
User user1 = new User();
user1.setUsername("chen");
user1.setCountry("China");
user1.setAge(30);
user1.setLenght(1.77f);
user1.setSalary(new BigDecimal("6885.22"));
Address address2 = new Address();
address2.setaCode("411000");
address2.setAdd("我的地址 2");
user1.setAddress(address2);
Favorites favorites2 = new Favorites();
favorites2.setCites(Arrays.asList("珠海","东京"));
favorites2.setMovies(Arrays.asList("东游记","一路向东"));
user1.setFavorites(favorites2);
//使用 insertMany 插入多条数据
doc.insertMany(Arrays.asList(user,user1));
}
@Test
public void testFind(){
final List<User> ret = new ArrayList<>();
Consumer<User> printDocument = new Consumer<User>() {
@Override
public void accept(User t) {
System.out.println(t.toString());
ret.add(t);
}
};
//select * from users where favorites.cites has "东莞"、"东京"
//db.users.find({ "favorites.cites" : { "$all" : [ "东莞" , "东京"]}})
Bson all = all("favorites.cites", Arrays.asList("东莞","东京"));//定义数据过滤器,喜欢的城市中要包含"东莞"、"东京" FindIterable<User> find = doc.find(all);
find.forEach(printDocument);
System.out.println("------------------>"+String.valueOf(ret.size()));
ret.removeAll(ret);
//select * from users where username like '%s%' and (contry= English or contry = USA)
// db.users.find({ "$and" : [ { "username" : { "$regex" : ".*c.*"}} , { "$or" : [ { "country" :
"English"} , { "country" : "USA"}]}]})
String regexStr = ".*c.*";
Bson regex = regex("username", regexStr);//定义数据过滤器,username like '%s%' Bson or = or(eq("country","English"),eq("country","USA"));//定义数据过滤器,(contry=English or contry = USA)
FindIterable<User> find2 = doc.find(and(regex,or));
find2.forEach(printDocument);
System.out.println("------------------>"+String.valueOf(ret.size()));
}
@Test
public void testUpdate(){
//update users set age=6 where username = 'lison' //db.users.updateMany({ "username" : "lison"},{ "$set" : { "age" : 6}},true)
Bson eq = eq("username", "lison");//定义数据过滤器,username = 'lison' Bson set = set("age", 8);//更新的字段.来自于 Updates 包的静态导入UpdateResult updateMany = doc.updateMany(eq, set);
System.out.println("------------------>"+String.valueOf(updateMany.getModifiedCount()));//打印受影响的行数
//update users set favorites.movies add "小电影 2 ", "小电影3" where favorites.cites
has "东莞"
//db.users.updateMany({ "favorites.cites" : "东莞"}, { "$addToSet" :
{ "favorites.movies" : { "$each" : [ "小电影 2 " , "小电影 3"]}}},true)
Bson eq2 = eq("favorites.cites", "东莞");//定义数据过滤器,favorites.cites has "东莞" Bson addEachToSet = addEachToSet("favorites.movies", Arrays.asList( "小电影2 ", "小电影 3"));//更新的字段.来自于 Updates 包的静态导入
UpdateResult updateMany2 = doc.updateMany(eq2, addEachToSet);
System.out.println("------------------>"+String.valueOf(updateMany2.getModifiedCount()));
}
@Test
public void testDelete(){
//delete from users where username = ‘lison’ //db.users.deleteMany({ "username" : "lison"} )
Bson eq = eq("username", "lison");//定义数据过滤器,username='lison' DeleteResult deleteMany = doc.deleteMany(eq);
System.out.println("------------------>"+String.valueOf(deleteMany.getDeletedCount()));//
打印受影响的行数
//delete from users where age >8 and age <25
//db.users.deleteMany({"$and" : [ {"age" : {"$gt": 8}} , {"age" : {"$lt" : 25}}]})
Bson gt = gt("age",8);//定义数据过滤器,age > 8,所有过滤器的定义来自于Filter
这个包的静态方法,需要频繁使用所以静态导入
Bson lt = lt("age",25);//定义数据过滤器,age < 25
Bson and = and(gt,lt);//定义数据过滤器,将条件用 and 拼接DeleteResult deleteMany2 = doc.deleteMany(and);
System.out.println("------------------>"+String.valueOf(deleteMany2.getDeletedCount()));//打印受影响的行数
}
}