目录
参考
MongoDB 连接
Java 连接 MongoDB 服务器,与我们常用的连接关系型数据库方式类似!
标准 URI 连接语法:
mongodb://username:password@host1:port1,host2:port2,...,hostN:portN/database?options
参数说明:
- mongodb://:这是固定的格式,必须要指定
- username:password@:可选项,如果设置,在连接数据库服务器之后,驱动都会尝试登录这个数据库
- host1:port1:主机IP和端口号,必须指定至少一个host。如果要连接复制集,请指定多个主机地址
- /database:如果指定了username:password@,连接时会验证并登录指定数据库。若不指定,默认打开 test 数据库
- ?options:连接可选项,例如connectTimeoutMS=5000ms,表示连接等待时间最长 5 秒
例如,无密码连接 MongoDB
mongodb://127.0.0.1:27017
使用用户名test,密码test登录 MongoDB 的test_db数据库
mongodb://test:test@127.0.0.1:27017/test_db
无密码连接指定三台服务器 (端口 27017, 27018, 和27019)
mongodb://127.0.0.1:27017,127.0.0.1:27018,127.0.0.1:27019
java客户端方式
引入驱动依赖
参考:https://docs.mongodb.com/drivers/java/
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.12.7</version>
</dependency>
测试创建客户端
public class MongoDBTest {
private static final String MONGO_URL = "localhost";
private MongoClient mongoClient = null;
@Test
public void testDb(){
// 连接到数据库
MongoDatabase mongoDatabase = mongoClient.getDatabase("test_iot");
System.out.println("Connect to database successfully");
mongoDatabase.createCollection("tower_crane_property");
System.out.println("集合创建成功");
}
@BeforeEach
public void initClient(){
//连接到MongoDB服务,如果不指定库名,则需要admin的账号密码 如果是远程连接可以替换“localhost”为服务器所在IP地址
mongoClient = MongoClients.create("mongodb://admin:123456@192.168.0.44:27017");
// 指定库
mongoClient = MongoClients.create("mongodb://admin:123456@192.168.0.44:27017/iot");
// 增加库在哪里认证,在哪里创建
mongoClient = MongoClients.create("mongodb://admin:123456@192.168.0.44:27017/iot?authSrouce=admin");
}
}
创建集合
可以通过ValidationOptions增加字段校验,也可以指定集合大小
查询文档
/**
* 查询文档
*/
@Test
public void testQuery() {
// 连接到数据库
MongoDatabase mongoDatabase = mongoClient.getDatabase("iot");
System.out.println("Connect to database successfully");
//获取集合
MongoCollection<org.bson.Document> collection = mongoDatabase.getCollection("device");
//遍历所有文档
FindIterable<org.bson.Document> findIterable = collection.find();
MongoCursor<org.bson.Document> mongoCursor = findIterable.iterator();
while(mongoCursor.hasNext()){
System.out.println(mongoCursor.next());
}
//查询当前集合所有文档数量
long count = collection.countDocuments();
System.out.println("当前文档数量:" + count);
//带条件遍历文档
FindIterable<Document> documentFindIterable = collection.find(Filters.eq("code", "manager"));
MongoCursor<Document> documentMongoCursor = documentFindIterable.iterator();
while(documentMongoCursor.hasNext()){
System.out.println(documentMongoCursor.next());
}
}
查询集合大小
//查询当前集合所有文档数量
long count = collection.countDocuments();
条件查询
排序
投影
聚合查询
对stars分组并计数
复合聚合
excludeId不显示id,只显示firstCategory字段,这个字段是显示categories索引小标0的值,也就是categories中第一个值
效果
插入文档
/**
* 测试插入
*/
@Test
public void testInsert(){
// 连接到数据库
MongoDatabase mongoDatabase = mongoClient.getDatabase("iot");
//获取集合
MongoCollection<Document> collection = mongoDatabase.getCollection("device");
//向集合中插入文档
Document document = new Document("name", "管理员").
append("code", "manager").
append("sort", 100).
append("lat", 22.81503471517295).
append("lng", 108.37301005337522);
List<Document> documents = new ArrayList<>();
documents.add(document);
collection.insertMany(documents);
System.out.println("文档插入成功");
}
批量插入
更新文档
删除文档
SpringDataMongoDB
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
配置文件
server:
port: 8083
spring:
data:
mongodb:
# 服务器地址
host: 192.168.0.44
# 端口
port: 27107
# 用户名
username: iot_admin
# 密码
password: iot_admin
# 认证数据库
authentication-database: iot
# 操作数据库
database: iot
新建实体映射
插入文档
修改文档
/**
* 更新对象
* @param user
*/
@Override
public void updateUser(UserEntity user) {
Query query=new Query(Criteria.where("id").is(user.getId()));
Update update= new Update().set("userName", user.getUserName()).set("passWord", user.getPassWord());
//更新查询返回结果集的第一条
mongoTemplate.updateFirst(query,update,UserEntity.class);
//更新查询返回结果集的所有
// mongoTemplate.updateMulti(query,update,UserEntity.class);
}
删除
/**
* 删除对象
* @param id
*/
@Override
public void deleteUserById(Long id) {
Query query=new Query(Criteria.where("id").is(id));
mongoTemplate.remove(query,UserEntity.class);
}
/***********方法二************/
/**
* 删除
*
* @param id id
* @return ApiResponse
*/
public ApiResponse delete(String id) {
try {
Query query = new Query(Criteria.where("_id").is(id));
DeleteResult result = mongoTemplate.remove(query, Student.class);
long count = result.getDeletedCount();
if (count > 0) {
return Api.ok(count, "删除成功");
}
throw new ServiceException(-1, String.format("【%s】%s", id, "不存在"));
} catch (ServiceException e) {
throw e;
} catch (Exception e) {
throw new SystemException(-1, "删除出错");
}
高级查询
查询某一天的数据
public PageDTO<ElevatorAlarmDTO> findTodayList(DevicePageQueryDTO param) {
/*
相差8个时区
24 = 16 + 8
db.getCollection("elevator_alarm").find({deviceCode:"1589581864182480897",timestamp:{"$gte":ISODate("2022-11-07T16:00:00.000Z")}}).sort({timestamp:-1})
*/
// todayStr = todayStr + "T16:00:00.000Z";
PageDTO<ElevatorAlarmDTO> result = new PageDTO<>();
int pageIndex = param.getPageIndex();
int pageSize = param.getPageSize();
result.setPageSize(pageSize);
//mongodb查询条件
Query query = new Query();
query.addCriteria(Criteria.where(IotConstant.FIELD_DEVICE_CODE).is(param.getDeviceCode()));
String todayStr = DateUtil.date().toDateStr();
Date today = DateUtil.parseDateTime(todayStr+" 00:00:00");
query.addCriteria(Criteria.where(IotConstant.FIELD_TIME).gte(today));
// 如下两种写法不可以
// query.addCriteria(Criteria.where(IotConstant.FIELD_TIMESTAMP).gte("ISODate(\""+todayStr+"\")"));
// query.addCriteria(Criteria.where(IotConstant.FIELD_TIMESTAMP).gte("ISODate(2022-11-07T16:00:00.000Z)"));
long count = mongoTemplate.count(query,getClazz());
result.setTotalCount(count);
if (count > 0){
long pageCount = (count+pageSize-1)/pageSize;
result.setPageCount(pageCount);
query.skip((long) (pageIndex - 1) * pageSize).limit(pageSize);
Sort sort = Sort.by(new Sort.Order(Sort.Direction.DESC, IotConstant.FIELD_TIME));
query.with(sort);
List<ElevatorAlarmDoc> data = mongoTemplate.find(query,getClazz());
if(data.size() > 0){
List<ElevatorAlarmDTO> rows = data.stream().map(ElevatorAlarmDoc::toDTO).collect(Collectors.toList());
result.setRows(rows);
}
}
return result;
}
统计最近七天趋势
public List<AlarmResultDTO> getAlarmWeekTrend(DeviceCodeQueryDTO param) {
/*
* db.getCollection("elevator_alarm").aggregate([ { "$match" : { "deviceCode" : "1589581864182480897"}}, { "$match" : { "timestamp" : { "$gte" : new Date("2022-11-02 00:00:00" ) } } }, { "$match" : { "timestamp" : { "$lte" : new Date("2022-11-08 23:59:59" )} } }, { "$project" : { "timestamp" : 1, "date" : { "$dateToString" : { "format" : "%Y-%m-%d", "date" : "$timestamp"}}}}, { "$group" : { "_id" : "$date", "count" : { "$sum" : 1}}}, { "$project" : { "count" : 1, "date" : "$_id"}}, { "$sort" : { "date" : 1}} ])
*/
String deviceCode = param.getDeviceCode();
DateTime today = DateUtil.date();
DateTime startDate = DateUtil.parseDateTime(DateUtil.offsetDay(today,-7).toDateStr()+" 00:00:00");
DateTime endDate = DateUtil.parseDateTime(today.toDateStr()+" 23:59:59");
// 如下两种方式都可以
//ProjectionOperation return1 = Aggregation.project(IotConstant.FIELD_TIME).andExpression("{$dateToString:{ format:'%Y-%m-%d',date: '$timestamp', timezone: 'Asia/Shanghai'}}").as("date");
ProjectionOperation return1 = Aggregation.project(IotConstant.FIELD_TIME).and(DateOperators.DateToString.dateOf(IotConstant.FIELD_TIME).toString("%Y-%m-%d")).as("date");
// 返回参数2,//如果不加这条,输出的结果如: [{"count": 3, "_id": "2019-12-13"}]
ProjectionOperation return2 = Aggregation.project("count").and("_id").as("date");
GroupOperation group = Aggregation.group("date").count().as("count");
Aggregation aggregation = Aggregation.newAggregation(
//where条件
Aggregation.match(Criteria.where(IotConstant.FIELD_DEVICE_CODE).is(deviceCode)),
//时间范围
Aggregation.match(Criteria.where(IotConstant.FIELD_TIME).gte(startDate)),
Aggregation.match(Criteria.where(IotConstant.FIELD_TIME).lte(endDate)),
//将时间戳格式化并重命名
//Aggregation.project("date").andExpression("{$dateToString: {date: { $add: {'$createTime', [0]} }, format: '%Y-%m-%d'}}", new Date(28800000)).as("date"),
return1,
// 返回参数
//分组统计
group,
return2,
//加上为: [{"count": 3, "date": "2019-12-13"}]
// Aggregation.project("date", "count").and("date").previousOperation(),
//排序
Aggregation.sort(Sort.Direction.ASC, "date"));
// 分组聚合查询
AggregationResults<AlarmResultDTO> aggregate = mongoTemplate.aggregate(aggregation,
ElevatorAlarmDoc.class, AlarmResultDTO.class);
// 获取结果
List<AlarmResultDTO> list = aggregate.getMappedResults();
List<AlarmResultDTO> result = new ArrayList<>();
Map<String,Long> resultMap = new HashMap<>();
if(list.size() > 0){
list.forEach(i->{resultMap.put(i.getDate(),i.getCount());});
}
for(int i = 0;i<7;i++){
DateTime d = startDate.offsetNew(DateField.DAY_OF_YEAR,i+1);
AlarmResultDTO item = new AlarmResultDTO();
item.setDate(d.toDateStr());
Long count = resultMap.get(d.toDateStr());
item.setCount(count == null?0:count);
result.add(item);
}
log.info("趋势:{}",result);
return result;
}