项目地址:
https://gitee.com/Anntly/mongo-crud
常见的 增删改查、地理位置、嵌套文档、聚合函数
新建项目
修改 application.yml 添加 mongodb数据源信息
spring:
data:
mongodb:
uri: mongodb://jboom:123456@127.0.0.1:27017/logistics
auto-index-creation: true
案例代码
以物流订单为例(非真实项目设计)
LogisticsOrder 物流订单
/**
* 物流订单
*/
@Data
@Document("logistics_order")
@ToString
public class LogisticsOrder {
/**
* 物流订单id
*/
@MongoId
@AutoId
private Long orderId;
/**
* 用户id
*/
private Long userId;
/**
* 订单价格
*/
private BigDecimal price;
/**
* 订单总重
*/
private BigDecimal weight;
/**
* 目的地
*/
private GeoJsonPoint to;
/**
* 出发地
*/
private GeoJsonPoint from;
/**
* 当前位置
*/
@GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE,useGeneratedName = true)
private GeoJsonPoint location;
/**
* 距离
*/
private transient Double distance;
/**
* 住址信息
*/
private Address address;
/**
* 运送物品
*/
private List<OrderItem> items;
/**
* 0 已发货
* 1 待收件
* 2 已揽收
* 3 运输中
* 4 配送中
* 5 已签收
*/
private Integer status;
/**
* 发出时间
*/
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private LocalDateTime sendTime;
/**
* 发出时间
*/
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private LocalDateTime receiveTime;
/**
* 操作者
*/
private String operator;
/**
* 操作时间
*/
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private LocalDateTime operateTime;
/**
* 备注
*/
private String remark;
}
OrderItem 订单货物
/**
* 物流货物
*/
@Data
@ToString
public class OrderItem {
/**
* 货物id
*/
private Long itemId;
/**
* 货物信息
*/
private String info;
/**
* 商品毛重
*/
private BigDecimal weight;
/**
* 商品价格
*/
private BigDecimal price;
}
Address 地址信息
@Data
@ToString
public class Address {
private String province;
private String city;
private String counties;
private String detail;
private String postCode;
}
CRUD
案例直接使用的MongoTemplate
@Resource
private MongoTemplate mongoTemplate;
新增订单
新增很简单
/**
* 新增订单
*
* @param order
* @return
*/
public Long addOrder(LogisticsOrder order) {
return mongoTemplate.insert(order).getOrderId();
}
查询订单,同时返回距离当前位置的距离
使用 NearQuery 包一层用于返回 GeoResult 获取 distance
/**
* mongodb一个集合最好只设计一个地理索引,多个会冲突
* 查询指定经纬度与数据的距离
*
* @param orderId
* @param longitude 收货地精度
* @param latitude 收货地纬度 -- 用于计算距离
* @return
*/
public LogisticsOrder getOrder(Long orderId, double longitude, double latitude) {
Criteria criteria = Criteria.where("_id").is(orderId);
Query query = new Query(criteria);
NearQuery nearQuery = NearQuery
.near(new GeoJsonPoint(longitude, latitude), Metrics.MILES)
.query(query);
GeoResults<LogisticsOrder> results = mongoTemplate.geoNear(nearQuery, LogisticsOrder.class);
for (GeoResult<LogisticsOrder> result : results) {
LogisticsOrder content = result.getContent();
double distance = result.getDistance().getValue();
content.setDistance(distance);
}
// 处理距离
return results.getContent().get(0).getContent();
}
查询坐标范围内的订单
/**
* 获取用户 range 公里范围(km)内的订单
*
* @param userId
* @param longitude
* @param latitude
* @param range
* @return
*/
public List<LogisticsOrder> getUserRangeOrder(Long userId, double longitude, double latitude, Integer range) {
GeoJsonPoint point = new GeoJsonPoint(longitude, latitude);
Distance distance = new Distance(range, Metrics.KILOMETERS);
// 圆圈范围内
Circle circle = new Circle(point, distance);
Criteria criteria = Criteria.where("userId").is(userId)
.and("location").withinSphere(circle);
Query query = new Query(criteria);
return mongoTemplate.find(query, LogisticsOrder.class);
}
修改订单
/**
* 操作员操作,发货、揽收、配送、签收等操作
*
* @param orderId
* @param operator
* @param longitude
* @param latitude
* @param status
* @return
*/
public boolean operateOrder(Long orderId, String operator, double longitude, double latitude, Integer status) {
Criteria criteria = Criteria.where("orderId").is(orderId);
Query query = new Query(criteria);
Update update = new Update().set("operator", operator)
.set("location", new GeoJsonPoint(longitude, latitude))
.set("status", status);
UpdateResult result = mongoTemplate.updateFirst(query, update, LogisticsOrder.class);
return result.getMatchedCount() != 0;
}
修改地址信息,嵌套子文档
/**
* 修改收货地址
* 修改嵌套子文档字段
*
* @param orderId
* @return
*/
public boolean modifyReceiveAddress(Long orderId, String province, String city,
String counties, String detail, String postCode) {
Criteria criteria = Criteria.where("_id").is(orderId);
Query query = new Query(criteria);
Update update = new Update();
Optional.ofNullable(province).ifPresent(p -> update.set("address.province", p));
Optional.ofNullable(city).ifPresent(c -> update.set("address.city", c));
Optional.ofNullable(counties).ifPresent(c -> update.set("address.counties", c));
Optional.ofNullable(detail).ifPresent(d -> update.set("address.detail", d));
Optional.ofNullable(postCode).ifPresent(p -> update.set("address.postCode", p));
return mongoTemplate.updateFirst(query, update, LogisticsOrder.class).getMatchedCount() > 0;
}
修改货物信息,嵌套子文档(数组)
/**
* 更新货物信息
* 更新嵌套数组对象字段信息
*
* @param orderId
* @param itemId
* @param weight
* @param price
* @param info
* @return
*/
public boolean modifyItem(Long orderId, Long itemId, BigDecimal weight, BigDecimal price, String info) {
Criteria criteria = Criteria.where("_id").is(orderId)
.and("items.itemId").is(itemId);
Query query = new Query(criteria);
Update update = new Update();
Optional.ofNullable(weight).ifPresent(w -> update.set("items.$.weight", w));
Optional.ofNullable(price).ifPresent(p -> update.set("items.$.price", p));
Optional.ofNullable(info).ifPresent(i -> update.set("items.$.info", i));
UpdateResult result = mongoTemplate.updateFirst(query, update, LogisticsOrder.class);
return result.getMatchedCount() != 0;
}
新增货物,嵌套子文档(数组)
/**
* 添加货物
* 嵌套数组添加元素
*
* @param orderId
* @param item
* @return
*/
public boolean addItem(Long orderId, OrderItem item) {
Criteria criteria = Criteria.where("_id").is(orderId);
Query query = new Query(criteria);
Update update = new Update();
// 不重复就用addToSet
update.push("items", item);
UpdateResult result = mongoTemplate.updateFirst(query, update, LogisticsOrder.class);
return result.getMatchedCount() != 0;
}
删除货物,嵌套子文档(数组)
/**
* 清除货物
* 嵌套数组删除元素
*
* @param orderId
* @param itemId
* @return
*/
public boolean removeItem(Long orderId, Long itemId) {
Criteria criteria = Criteria.where("_id").is(orderId);
Query query = new Query(criteria);
BasicDBObject dbObject = new BasicDBObject();
dbObject.put("itemId", itemId);
Update update = new Update();
update.pull("items", dbObject);
UpdateResult result = mongoTemplate.updateFirst(query, update, LogisticsOrder.class);
return result.getMatchedCount() != 0;
}
统计用户不同状态的订单数,聚合
/**
* 统计用户每个状态的订单数
*
* @param userId
* @return
*/
public void userStatusOrderNum(Long userId) {
AggregationOperation match = Aggregation.match(Criteria.where("userId").is(userId));
AggregationOperation group = Aggregation.group("status").count().as("orderNum");
Aggregation aggregation = Aggregation.newAggregation(match, group);
AggregationResults<Map> aggregate = mongoTemplate.aggregate(aggregation, LogisticsOrder.class, Map.class);
for (Map map : aggregate) {
System.out.println(map);
}
}
版权声明:本文为ticktak原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。