release: 门店distance排序用mysql实现

release-2024-04-25
huangyw 3 months ago
parent 2f36cd7637
commit 5073c129d9

@ -148,6 +148,12 @@
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.5</version>
</dependency>
<!-- QueryDSL框架依赖 --> <!-- QueryDSL框架依赖 -->
<dependency> <dependency>
<groupId>com.querydsl</groupId> <groupId>com.querydsl</groupId>

@ -3,6 +3,8 @@ package com.luoo.user.controller;
import annotation.GlobalInterceptor; import annotation.GlobalInterceptor;
import api.PageResult; import api.PageResult;
import api.Result; import api.Result;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.luoo.user.dto.store.StoreAddDto; import com.luoo.user.dto.store.StoreAddDto;
import com.luoo.user.dto.store.StoreSearchDto; import com.luoo.user.dto.store.StoreSearchDto;
import com.luoo.user.dto.store.StoreUpdateDto; import com.luoo.user.dto.store.StoreUpdateDto;
@ -45,13 +47,19 @@ public class StoreController {
return Result.success(storeService.getList(storeSearchDto, page, size)); return Result.success(storeService.getList(storeSearchDto, page, size));
} }
@PostMapping("/app/list") @PostMapping("/app/list/{page}/{size}")
@ApiOperation(value = "获取门店列表(APP)", notes = "获取门店列表") @ApiOperation(value = "获取门店列表(APP)", notes = "获取门店列表")
@GlobalInterceptor(checkAppUserLogin = true) @GlobalInterceptor(checkAppUserLogin = true)
public Result<List<StoreAppVO>> getStoreList( public Result<PageResult<StoreAppVO>> getStoreList(
@ApiParam(value = "查询内容") @RequestBody StoreSearchDto storeSearchDto @ApiParam(value = "查询内容") @RequestBody StoreSearchDto storeSearchDto,
@ApiParam(value = "页码", required = true) @PathVariable Integer page,
@ApiParam(value = "每页条数", required = true) @PathVariable Integer size
) { ) {
return Result.success(storeService.getListForApp(storeSearchDto)); PageHelper.startPage(page, size);
List<StoreAppVO> listForApp = storeService.getListForApp(storeSearchDto);
PageInfo pageInfo = new PageInfo(listForApp);
PageResult<StoreAppVO> result = new PageResult<>(pageInfo.getTotal(), listForApp);
return Result.success(result);
} }
@GetMapping("/get") @GetMapping("/get")

@ -0,0 +1,13 @@
package com.luoo.user.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.luoo.user.dto.store.StoreSearchDto;
import com.luoo.user.pojo.Store;
import com.luoo.user.vo.store.StoreAppVO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface StoreMapper extends BaseMapper<Store> {
public List<StoreAppVO> getListForApp(@Param("storeSearchDto") StoreSearchDto storeSearchDto);
}

@ -4,6 +4,7 @@ import api.PageResult;
import com.luoo.user.dao.StoreDao; import com.luoo.user.dao.StoreDao;
import com.luoo.user.dto.store.StoreSearchDto; import com.luoo.user.dto.store.StoreSearchDto;
import com.luoo.user.dto.store.StoreUpdateDto; import com.luoo.user.dto.store.StoreUpdateDto;
import com.luoo.user.mapper.StoreMapper;
import com.luoo.user.pojo.QStore; import com.luoo.user.pojo.QStore;
import com.luoo.user.pojo.Region; import com.luoo.user.pojo.Region;
import com.luoo.user.pojo.Store; import com.luoo.user.pojo.Store;
@ -54,13 +55,16 @@ public class StoreService {
private final RabbitTemplate rabbitTemplate; private final RabbitTemplate rabbitTemplate;
public StoreService(StoreDao storeDao, JPAQueryFactory jpaQueryFactory, RegionService regionService, RedisTemplate redisTemplate, UserInfoService userInfoService, RabbitTemplate rabbitTemplate) { private final StoreMapper storeMapper;
public StoreService(StoreDao storeDao, JPAQueryFactory jpaQueryFactory, RegionService regionService, RedisTemplate redisTemplate, UserInfoService userInfoService, RabbitTemplate rabbitTemplate, StoreMapper storeMapper) {
this.storeDao = storeDao; this.storeDao = storeDao;
this.jpaQueryFactory = jpaQueryFactory; this.jpaQueryFactory = jpaQueryFactory;
this.regionService = regionService; this.regionService = regionService;
this.redisTemplate = redisTemplate; this.redisTemplate = redisTemplate;
this.userInfoService = userInfoService; this.userInfoService = userInfoService;
this.rabbitTemplate = rabbitTemplate; this.rabbitTemplate = rabbitTemplate;
this.storeMapper = storeMapper;
} }
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@ -188,67 +192,72 @@ public class StoreService {
} }
public List<StoreAppVO> getListForApp(StoreSearchDto storeSearchDto) { public List<StoreAppVO> getListForApp(StoreSearchDto storeSearchDto) {
BooleanBuilder booleanBuilder = new BooleanBuilder();
QStore qStore = QStore.store;
// APP只查询合作中的门店
storeSearchDto.setStatus(StoreEnums.STORE_STATUS_COOPERATION.getCode()); storeSearchDto.setStatus(StoreEnums.STORE_STATUS_COOPERATION.getCode());
checkCondition(booleanBuilder, qStore, storeSearchDto);
List<StoreAppVO> storeList = jpaQueryFactory.select(Projections.constructor(StoreAppVO.class,
qStore.id,
qStore.name,
qStore.regionId,
qStore.address,
qStore.lng,
qStore.lat,
qStore.contact,
qStore.phone,
qStore.tel,
qStore.openingHours,
qStore.background,
qStore.description,
qStore.visitCount,
qStore.introduction,
qStore.code
)).from(qStore)
.where(booleanBuilder)
.orderBy(qStore.createTime.desc())
.fetch();
double lng = storeSearchDto.getLng() == null ? 0 : Double.parseDouble(storeSearchDto.getLng());
double lat = storeSearchDto.getLng() == null ? 0 : Double.parseDouble(storeSearchDto.getLat());
UUID uuid = UUID.randomUUID();
redisTemplate.opsForGeo().add(String.valueOf(uuid), new Point(lng, lat), "current");
storeList.forEach(store -> {
String contact = store.getContact();
if (StringUtils.isNotBlank(contact)) {
UserInfo byId = userInfoService.findById(contact);
store.setContactNickName(byId == null ? "" : byId.getNickName());
store.setContactAvatar(byId == null ? "" : byId.getAvatar());
}
redisTemplate.opsForGeo().add(String.valueOf(uuid),
new Point(Double.parseDouble(store.getLng()), Double.parseDouble(store.getLat())),
"location");
Double distance = getDistance(String.valueOf(uuid), "current", "location");
log.info("distance:{}", distance);
store.setDistance(distance);
}); List<StoreAppVO> storeList = storeMapper.getListForApp(storeSearchDto);
// 按StoreAppVO.getDistance从近到远排序生成新的list
storeList.sort((o1, o2) -> { // BooleanBuilder booleanBuilder = new BooleanBuilder();
if (o1.getDistance() == null) { // QStore qStore = QStore.store;
return 1; // // APP只查询合作中的门店
} // storeSearchDto.setStatus(StoreEnums.STORE_STATUS_COOPERATION.getCode());
if (o2.getDistance() == null) { // checkCondition(booleanBuilder, qStore, storeSearchDto);
return -1; //
} // List<StoreAppVO> storeList = jpaQueryFactory.select(Projections.constructor(StoreAppVO.class,
return o1.getDistance().compareTo(o2.getDistance()); // qStore.id,
}); // qStore.name,
redisTemplate.delete(String.valueOf(uuid)); // qStore.regionId,
// qStore.address,
// qStore.lng,
// qStore.lat,
// qStore.contact,
// qStore.phone,
// qStore.tel,
// qStore.openingHours,
// qStore.background,
// qStore.description,
// qStore.visitCount,
// qStore.introduction,
// qStore.code
// )).from(qStore)
// .where(booleanBuilder)
// .orderBy(qStore.createTime.desc())
// .fetch();
//
// double lng = storeSearchDto.getLng() == null ? 0 : Double.parseDouble(storeSearchDto.getLng());
// double lat = storeSearchDto.getLng() == null ? 0 : Double.parseDouble(storeSearchDto.getLat());
//
// UUID uuid = UUID.randomUUID();
// redisTemplate.opsForGeo().add(String.valueOf(uuid), new Point(lng, lat), "current");
//
// storeList.forEach(store -> {
// String contact = store.getContact();
// if (StringUtils.isNotBlank(contact)) {
// UserInfo byId = userInfoService.findById(contact);
// store.setContactNickName(byId == null ? "" : byId.getNickName());
// store.setContactAvatar(byId == null ? "" : byId.getAvatar());
// }
//
// redisTemplate.opsForGeo().add(String.valueOf(uuid),
// new Point(Double.parseDouble(store.getLng()), Double.parseDouble(store.getLat())),
// "location");
// Double distance = getDistance(String.valueOf(uuid), "current", "location");
// log.info("distance:{}", distance);
// store.setDistance(distance);
//
// });
//
// // 按StoreAppVO.getDistance从近到远排序生成新的list
// storeList.sort((o1, o2) -> {
// if (o1.getDistance() == null) {
// return 1;
// }
// if (o2.getDistance() == null) {
// return -1;
// }
// return o1.getDistance().compareTo(o2.getDistance());
// });
// redisTemplate.delete(String.valueOf(uuid));
return storeList; return storeList;

@ -81,7 +81,7 @@ public class StoreAppVO implements Serializable {
public StoreAppVO() { public StoreAppVO() {
} }
public StoreAppVO(String id, String name, Integer regionId, String address, String lng, String lat, String contact, String phone, String tel, String openingHours, String background, String description, Region region, Double distance, Integer visitCount, String introduction, String code) { public StoreAppVO(String id, String name, Integer regionId, String address, String lng, String lat, String contact, String phone, String tel, String openingHours, String background, String description, Integer visitCount, String introduction, String code) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.regionId = regionId; this.regionId = regionId;
@ -94,8 +94,6 @@ public class StoreAppVO implements Serializable {
this.openingHours = openingHours; this.openingHours = openingHours;
this.background = background; this.background = background;
this.description = description; this.description = description;
this.region = region;
this.distance = distance;
this.visitCount = visitCount; this.visitCount = visitCount;
this.introduction = introduction; this.introduction = introduction;
this.code = code; this.code = code;

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.luoo.user.mapper.StoreMapper">
<resultMap id="BaseResultMap" type="com.luoo.user.vo.store.StoreAppVO">
<id property="id" column="id" jdbcType="VARCHAR"/>
<result property="name" column="name" jdbcType="VARCHAR"/>
<result property="regionId" column="region_id" jdbcType="INTEGER"/>
<result property="address" column="address" jdbcType="VARCHAR"/>
<result property="lng" column="lng" jdbcType="VARCHAR"/>
<result property="lat" column="lat" jdbcType="VARCHAR"/>
<result property="contact" column="contact" jdbcType="VARCHAR"/>
<result property="phone" column="phone" jdbcType="VARCHAR"/>
<result property="tel" column="tel" jdbcType="VARCHAR"/>
<result property="openingHours" column="openingHours" jdbcType="VARCHAR"/>
<result property="background" column="background" jdbcType="VARCHAR"/>
<result property="description" column="description" jdbcType="VARCHAR"/>
<result property="contactAvatar" column="contact_avatar" jdbcType="VARCHAR"/>
<result property="contactNickName" column="contact_nick_name" jdbcType="VARCHAR"/>
<result property="distance" column="distance" jdbcType="DOUBLE"/>
<result property="visitCount" column="visit_count" jdbcType="INTEGER"/>
<result property="introduction" column="introduction" jdbcType="VARCHAR"/>
<result property="code" column="code" jdbcType="VARCHAR"/>
</resultMap>
<select id="getListForApp" resultMap="BaseResultMap">
SELECT t1.*, t2.avatar contact_avatar, t2.nick_name contact_nick_name,
st_distance_sphere(point(lng, lat), point(#{storeSearchDto.lng}, #{storeSearchDto.lat})) as distance
FROM tb_store t1
left join tb_user_info t2
on t1.contact = t2.id
WHERE 1=1
<if test="storeSearchDto.searchStr != null and storeSearchDto.searchStr != ''">
and (t1.name like concat('%',#{storeSearchDto.searchStr},'%')
or t1.contact like concat('%',#{storeSearchDto.searchStr},'%')
or t1.phone like concat('%',#{storeSearchDto.searchStr},'%'))
</if>
<if test="storeSearchDto.startTime != null">
and t1.create_time >= #{storeSearchDto.startTime}
</if>
<if test="storeSearchDto.endTime != null">
and t1.create_time <![CDATA[ <= ]]> #{storeSearchDto.endTime}
</if>
<if test="storeSearchDto.status != null">
and t1.status = #{storeSearchDto.status}
</if>
ORDER BY distance
</select>
</mapper>
Loading…
Cancel
Save