首先,cmd命令行打开MongoDB连接,use使用test(自行更换自己使用的库)库。查看owner表内上一篇中创建的数据。这里贴一个测试数据的json数据结构。
var owner1 = {
name: "张三",
age: 25,
books: {
name: "天涯明月刀",
author: "古龙"
},
favorites: {
movies: ["盗梦空间", "杀破狼", "羞羞的铁拳"],
cites: ["北京", "上海", "深圳"]
},
salary: NumberDecimal("100.05")
};
--- java程序获取mongoDB数据库及集合连接
1.程序pom文件引入mongoDB原生java驱动包。更新并clean项目。
<!-- mongoDB原生java驱动 -->
<!-- 3.5之后的版本,新增了对java的pojo的支持 -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.5.0</version>
</dependency>
2.建立测试service类。声明3个变量:MongoClient、MongoDatabase、MongoCollection,如图:
import org.bson.Document;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.MongoClient;
/**
* mongodb连接池
*/
private MongoClient client;
/**
* mongoDB库
*/
private MongoDatabase db;
/**
* mongoDB集合,泛型为mongoDB文档
*/
private MongoCollection<Document> mongoCollection;
首先。mongoClient为mongoDB提供的连接client,内部提供了mongoDB连接池,不需要再引用第三方依赖,并且在官方文档中详细说明了:这个client是线程安全的,因此大部分情况下,jvm中只需要存在一个client实例。
从mongoClient中可以获取目标库,继而连接目标集合。
MongoCollection<Document>,泛型类型为Document。在mongoDB原生驱动内,所有数据元素均为文档--Document。文档并不限制具体类型,也不限制文档内属性数量及属性类型。与java的model参照对比理解。
3.通过mongoClient获取目标mongo实例连接,并拿到目标库及集合连接。
@Before // junit测试使用注解
public void init() {
// mongoDB实例ip, 端口(默认27017)
client = new MongoClient("localhost", 27017);
// 目标库
db = client.getDatabase("las");
// 目标集合
mongoCollection = db.getCollection("users");
}
mongoDB连接及库和集合都初始化完毕后,开始java代码中对数据的简单CRUD实现。
--- 使用原生java驱动,操作Document文档,实现简单CRUD
5.新增insert。数据格式参照本文开头json数据格式。
@Test
public void insert() {
Document doc = new Document();
// -------- 基本属性 --------
doc.append("name", "李六");
doc.append("age", 17);
doc.append("salary", new BigDecimal("5000.21"));
// ------- 属性值为简单对象 -------
Map<String, String> books = new HashMap<>();
books.put("name", "北平往事");
books.put("author", "不知道");
doc.append("books", books);
// ------------ 属性值为对象,内包含不同数据类型。数组集合等 ----------
Map<String, Object> favorites = new HashMap<>();
favorites.put("movies", Arrays.asList("三体", "人工智能", "终结者"));
favorites.put("cites", Arrays.asList("河南", "湖南", "海南"));
doc.append("favorites", favorites);
// 使用init()方法内获取的目标集合连接实例,向该集合内插入一个文档
mongoCollection.insertOne(doc);
}
junit测试运行insert方法,在cmd中查询db.owner.find(),成功添加一条记录。
6.删除delete。注释采用关系型sql语言说明目的,并将mongoDB中实现相同目的代码贴出。
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.model.Filters;
@Test
public void delete() {
// delete from owner where name = "张三"
Bson f1 = Filters.eq("name", "张三");
// 删除满足条件的所有文档
DeleteResult result1 = mongoCollection
.deleteMany(f1);
LOG.info("删除了:: " + String.valueOf(result1));
// delete from owner where age > 25 or age < 5
Bson f2 = Filters.gt("age", 25)
Bson f3 = Filters.lt("age", 5)
Bson f4 = Filters.or(f2, f3)
// 删除满足条件的所有文档
DeleteResult result2 = mongoCollection.deleteMany(f4);
LOG.info("第二次删除了 :::: " + String.valueOf(result2));
}
7.更新update。
import com.mongodb.client.result.UpdateResult;
import com.mongodb.client.model.Updates;
@Test
public void update() {
// update owner set age = 4 where name = "王五"
// 使用替换更新。注意此处与操作符更新区别。
// Document doc = new Document("age", 4);
// 使用操作符更新。注意此处与替换更新区别。
Document doc = new Document("$set", new Document("age", 4));
// 执行更新。
UpdateResult result1 = mongoCollection.updateMany(
Filters.eq("name", "王五"), doc);
// 打印日志:匹配数量,更新数量。
LOG.info(String.valueOf(result1.getMatchedCount()), " ",
String.valueOf(result1.getModifiedCount()));
// -------------------------------------------------------------------------------
// update owner set favorites.movies add "大片1" "大片2" ---并非有效sql语句,仅为说明目的
// where favorites.cites has "北京" or "纽约"
// 使用Updates的addEachToSet方法,将传入的list内的每一个元素都add进目标属性的list最后
Bson arrayToAdd = Updates.addEachToSet("favorites.movies",
Arrays.asList("大片1", "大片2"));
// 执行更新
UpdateResult result2 = mongoCollection.updateMany(
Filters.or(Filters.eq("favorites.cites", "北京"),
Filters.eq("favorites.cites", "纽约")), arrayToAdd );
LOG.info(String.valueOf(result2.getMatchedCount()), " ",
String.valueOf(result2.getModifiedCount()));
}
注:替换更新new Document("age", 4),会将name = “王五”的文档,更新为只有 "age"属性并且值为4的文档。
操作符更新new Document("$set", new Document("age", 4)),才会仅修改name = "王五"的文档内age属性值为4。
8.查询find。重点。所有的更新、删除、都需要查询作为条件。
import com.mongodb.Block;
import com.mongodb.client.FindIterable;
@Test
public void find() {
// 查询结果集合。必须使用final声明
final List<Document> resultList = new ArrayList<>();
// 查询结果块。Document类型
Block<Document> block = new Block<Document>() {
// 调用,将每一个Document传入此中
@Override
public void apply(Document t) {
LOG.info(t.toJson());
resultList.add(t);
}
};
// select * from owner where favorites.cites has "上海" "华盛顿"
FindIterable<Document> result1 = mongoCollection.find(
Filters.all("favorites.cites", Arrays.asList("深圳", "北京")));
// find()方法查到返回的结果为游标,需要将此遍历并使用Block接受转换为Document
result1.forEach(block);
LOG.info("查询1---------------------");
LOG.info(String.valueOf(resultList.size()));
// 清空查询结果集合
resultList.clear();
// select * from owner
// where name like '%李%'
// and (favorites.cites has '印度' or favorites.cites has 纽约)
String regex = ".*李.*"; // mongoDB内的like模糊查询。使用正则表达式完成
Bson f1 = Filters.regex("name", regex);
Bson f2 = Filters.or(Filters.eq("favorites.cites", "印度"),
Filters.eq("favorites.cites", "纽约"));
FindIterable<Document> result2 = mongoCollection
.find(Filters.and(f1, f2));
result2.forEach(block);
LOG.info("查询2---------------------");
LOG.info(String.valueOf(resultList.size()));
}
9.上述方法中,使用到的Filters,Updates等包括后面将会用到的一些,mongoDB提供的数据操作类,在类的说明上也有标明:建议静态导入所有的方法,在使用该类内提供的静态方法时可省略类名。
注:慎重使用删除和替换更新,防止数据丢失!!! 如若不慎手滑,请参照本文标题解决~~。