获取用户star的所有项目信息(支持分页和关键字检索)
2016-08-28 21:32
381 查看
之前做的一个项目,现在做个小结。
query 关键字 可选
type 项目所属类型检索条件 可选
sub_type 项目所属子类型检索条件 可选
language 编程语言检索条件 可选
tag 标签索引条件 可选
direction 排序顺序desc,asc,默认desc 可选
sort created默认(按star时间)updated(按项目更新时间)stars(按stars数量) 可选
page 页码,请求第几页数据(默认值:1) 可选
size 每页数量(默认值:30) 可选
1、controller层
@RestController
@RequestMapping(value = "/v0.1/user")
public class UserController {
@Resource
private ProjectStarRecordService projectStarRecordService;
/**
* 用户star项目列表
*
* @param direction
* @param sort
* @param page
* @param size
* @param userInfo 登录用户信息,直接从Headers中取得
* @return
*/
@RequestMapping(value = "/stars", method = RequestMethod.GET)
public Object projectStaredByUser(@RequestParam(value = "query", defaultValue = "") String keyword,
@RequestParam(value = "type", required = false) String type,
@RequestParam(value = "sub_type", required = false) String subType,
@RequestParam(value = "language", required = false) String language,
@RequestParam(value = "tag", required = false) String tag,
@RequestParam(value = "direction", defaultValue = "DESC") String direction,
@RequestParam(value = "sort", defaultValue = "created") String sort,
@RequestParam(value = "page", defaultValue = "1") int page,
@RequestParam(value = "size", defaultValue = "30") int size,
@AuthenticationPrincipal UserInfo userInfo) {
// 判断用户是否存在
if (null == userInfo) {
throw new WafAuthenticationException("该用户不存在");
}
// 将sort转化成数据库对应的字段名称
if (sort.equals("created")) {
sort = "star_time";
} else if (sort.equals("updated")) {
sort = "last_activity_at";
} else {
sort = "stars";
}
return projectStarRecordService.getUserStarProject( keyword, type, subType, language, tag, direction, sort, page, size,userInfo);
}
}2、service层
/**
* 关键字检索
*
* @param keyword 关键字
* @param categories 维度map:key为维度值,value为类别值数组
* @param direction 排序方式,ASC 升序, DESC 降序
* @param sort 要排序的字段
* @param page 当前页码
* @param size 每页显示数据条数
* @return
*/
@Override
public List<ProjectInfo> search(Collection<String> projectIds, String keyword, Map<String, List<String>> categories, String direction, String sort, int page, int size) {
Query query = makeSearchQuery(keyword, categories, projectIds);
// 排序规则
query.with(new Sort(Sort.Direction.valueOf(direction.toUpperCase()), sort));
query.with(new PageRequest(page - 1, size));
return mongoTemplate.find(query, ProjectInfo.class);
}
@Override
public long count(String keyword, Map<String, List<String>> categories, Collection<String> projectIds) {
Query query = makeSearchQuery(keyword, categories, projectIds);
return mongoTemplate.count(query, ProjectInfo.class);
}
private Query makeSearchQuery(String keyword, Map<String, List<String>> categories, Collection<String> projectIds) {
Query query = new Query();
Criteria c = new Criteria();
if (StringUtils.isNotBlank(keyword)) {// 对name和description进行全文检索
// TextCriteria tc = TextCriteria.forLanguage("hans");
// query.addCriteria(tc.matchingAny(keyword));
// 2.x mongodb 不知支持中文的全文检索,改用正则
String regexp = String.format("%s", keyword);
c.orOperator(Criteria.where("name").regex(regexp), Criteria.where("description").regex(regexp)).and("_id").in(projectIds);
} else {
query.addCriteria(Criteria.where("_id").in(projectIds));
}
c.and("delete_flag").is(false);
// 维度下面的精确匹配
String category = "categories.";
if (null != categories) {
for (Map.Entry<String, List<String>> entry : categories.entrySet()) {
String dimension = entry.getKey();
List<String> dimensionValues = entry.getValue();
c.and(category + dimension).in(dimensionValues);
}
}
query.addCriteria(c);
return query;
}4、model层
主要涉及到的表:
项目基本信息(project_info)
{
"id":"",//主键
"name":"", //名称
"description":"",//描述
"is_available":false,//是否可用
"is_public":false, //是否公开
"create_at":"", //项目创建时间
"last_activity_at":"", //最后一次更新时间
"is_starred_by_current_user":false,
"owner":{ //拥有者
"id":"", //拥有者id,uc的user_id
"name":"", //拥有者的名字
"user_name":"" //拥有者的工号
},
"stars" : NumberLong(0),
"web_url":"", //项目首页地址,预留
"repo_url":"", //仓库地址,gitlab or svn
"avatar_url":"", //项目logo
"categories":{ //项目所属类别
"language":[], //编程语言
"type":[], //项目所属类别 web or 组件
"sub_type":[], //项目所属子类别 web应用 移动应用 web组件 ios组件 android组件
"tag":[] //项目标签
},
"members":[ //项目成员
{
"id":"", //拥有者id,uc的user_id
"name":"", //项目成员姓名
"user_name":"", //项目成员工号
"role":"" //项目成员角色,如:主程,开发者,策划,测试
}
]
}维度(dimension)
query 关键字 可选
type 项目所属类型检索条件 可选
sub_type 项目所属子类型检索条件 可选
language 编程语言检索条件 可选
tag 标签索引条件 可选
direction 排序顺序desc,asc,默认desc 可选
sort created默认(按star时间)updated(按项目更新时间)stars(按stars数量) 可选
page 页码,请求第几页数据(默认值:1) 可选
size 每页数量(默认值:30) 可选
1、controller层
@RestController
@RequestMapping(value = "/v0.1/user")
public class UserController {
@Resource
private ProjectStarRecordService projectStarRecordService;
/**
* 用户star项目列表
*
* @param direction
* @param sort
* @param page
* @param size
* @param userInfo 登录用户信息,直接从Headers中取得
* @return
*/
@RequestMapping(value = "/stars", method = RequestMethod.GET)
public Object projectStaredByUser(@RequestParam(value = "query", defaultValue = "") String keyword,
@RequestParam(value = "type", required = false) String type,
@RequestParam(value = "sub_type", required = false) String subType,
@RequestParam(value = "language", required = false) String language,
@RequestParam(value = "tag", required = false) String tag,
@RequestParam(value = "direction", defaultValue = "DESC") String direction,
@RequestParam(value = "sort", defaultValue = "created") String sort,
@RequestParam(value = "page", defaultValue = "1") int page,
@RequestParam(value = "size", defaultValue = "30") int size,
@AuthenticationPrincipal UserInfo userInfo) {
// 判断用户是否存在
if (null == userInfo) {
throw new WafAuthenticationException("该用户不存在");
}
// 将sort转化成数据库对应的字段名称
if (sort.equals("created")) {
sort = "star_time";
} else if (sort.equals("updated")) {
sort = "last_activity_at";
} else {
sort = "stars";
}
return projectStarRecordService.getUserStarProject( keyword, type, subType, language, tag, direction, sort, page, size,userInfo);
}
}2、service层
public Object getUserStarProject(String keyword, String type, String subType, String language, String tag, String direction, String sort, int page, int size, UserInfo userInfo) { List<ProjectStarRecord> projectStarRecordList = findByUserId(userInfo.getUserId()); if (null == projectStarRecordList || projectStarRecordList.isEmpty()) { return Collections.emptyList(); } // 遍历star项目,得到项目ID放入集合中用于mongodb查询 Collection<String> projectIdList = Collections2.transform(projectStarRecordList, new Function<ProjectStarRecord, String>() { @Override public String apply(ProjectStarRecord input) { return input.getProjectId(); } }); // 返回该用户star的所有项目信息,并且进行分页操作 PageVo<ProjectInfo> pv = projectInfoService.findById(projectIdList, keyword, type, subType, language, tag, direction, sort, page, size); PageVo<Map> pageVo = formatUserStarProject(projectStarRecordList, pv); //重新获得值 return pageVo; }
private PageVo<Map> formatUserStarProject(List<ProjectStarRecord> projectStarRecordList, PageVo<ProjectInfo> pv) { List<ProjectInfo> items = pv.getItems(); List<Map> resList = new ArrayList<>(); for (ProjectInfo info : items) { Map<String, Object> map = new HashMap<>(); map.put("name", info.getName()); map.put("description", info.getDescription()); map.put("last_activity_at", info.getLastActivityAt()); map.put("id", info.getId()); // map.put("star_time", new Date(0L)); for (ProjectStarRecord record : projectStarRecordList) { if (record.getProjectId().equals(info.getId())) { map.put("star_time", record.getStarTime()); } } resList.add(map); } PageVo<Map> pageVo = new PageVo<>(); pageVo.setItems(resList); pageVo.setTotalCount(pv.getTotalCount()); pageVo.setTotalPage(pv.getTotalPage()); pageVo.setPage(pv.getPage()); pageVo.setSize(pv.getSize()); return pageVo; }
/** * 获取用户star的项目的所有信息列表 * * @param projectIds * @param direction * @param sort * @param page * @param size * @return */ public PageVo<ProjectInfo> findById(Collection<String> projectIds, String keyword, String type, String subType, String language, String tag, String direction, String sort, int page, int size) { Map<String, List<String>> categories = new HashMap<>(); appendCategory(categories, "type", type); appendCategory(categories, "sub_type", subType); appendCategory(categories, "language", language); appendCategory(categories, "tag", tag); List<ProjectInfo> projectInfoList = projectInfoRepository.search(projectIds, keyword, categories, direction, sort, page, size); // 分页结果 long total = projectInfoRepository.count(keyword, categories, projectIds); PageVo<ProjectInfo> pageVo = new PageVo<>(); pageVo.setItems(projectInfoList); pageVo.setTotalCount(total); pageVo.setTotalPage(size == 0 ? 1 : (int) Math.ceil((double) total / (double) size)); pageVo.setPage(page); pageVo.setSize(size); return pageVo; }3、repository层
/**
* 关键字检索
*
* @param keyword 关键字
* @param categories 维度map:key为维度值,value为类别值数组
* @param direction 排序方式,ASC 升序, DESC 降序
* @param sort 要排序的字段
* @param page 当前页码
* @param size 每页显示数据条数
* @return
*/
@Override
public List<ProjectInfo> search(Collection<String> projectIds, String keyword, Map<String, List<String>> categories, String direction, String sort, int page, int size) {
Query query = makeSearchQuery(keyword, categories, projectIds);
// 排序规则
query.with(new Sort(Sort.Direction.valueOf(direction.toUpperCase()), sort));
query.with(new PageRequest(page - 1, size));
return mongoTemplate.find(query, ProjectInfo.class);
}
@Override
public long count(String keyword, Map<String, List<String>> categories, Collection<String> projectIds) {
Query query = makeSearchQuery(keyword, categories, projectIds);
return mongoTemplate.count(query, ProjectInfo.class);
}
private Query makeSearchQuery(String keyword, Map<String, List<String>> categories, Collection<String> projectIds) {
Query query = new Query();
Criteria c = new Criteria();
if (StringUtils.isNotBlank(keyword)) {// 对name和description进行全文检索
// TextCriteria tc = TextCriteria.forLanguage("hans");
// query.addCriteria(tc.matchingAny(keyword));
// 2.x mongodb 不知支持中文的全文检索,改用正则
String regexp = String.format("%s", keyword);
c.orOperator(Criteria.where("name").regex(regexp), Criteria.where("description").regex(regexp)).and("_id").in(projectIds);
} else {
query.addCriteria(Criteria.where("_id").in(projectIds));
}
c.and("delete_flag").is(false);
// 维度下面的精确匹配
String category = "categories.";
if (null != categories) {
for (Map.Entry<String, List<String>> entry : categories.entrySet()) {
String dimension = entry.getKey();
List<String> dimensionValues = entry.getValue();
c.and(category + dimension).in(dimensionValues);
}
}
query.addCriteria(c);
return query;
}4、model层
public class PageVo<T> { // 总数 private long totalCount; // 总页数 private int totalPage; // 页码 private int page; // 单页数量 private int size; // 结果列表 private List<T> items; public List<T> getItems() { return items; } public void setItems(List<T> items) { this.items = items; } public long getTotalCount() { return totalCount; } public void setTotalCount(long totalCount) { this.totalCount = totalCount; } public int getTotalPage() { return totalPage; } public void setTotalPage(int totalPage) { this.totalPage = totalPage; } public int getPage() { return page; } public void setPage(int page) { this.page = page; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } }
@Document(collection = "project_star_record") public class ProjectStarRecord extends BaseEntity { @Indexed @Field("project_id") private String projectId; @Indexed @Field("user_id") private String userId; @Indexed @CreatedDate @Field("star_time") private Date starTime; public Date getStarTime() { return starTime; } public void setStarTime(Date starTime) { this.starTime = starTime; } public String getProjectId() { return projectId; } public void setProjectId(String projectId) { this.projectId = projectId; } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } }
@Document(collection = "project_info") public class ProjectInfo extends BaseEntity { @TextIndexed(weight = 3) private String name; @TextIndexed(weight = 2) private String description; @Field("nick_name") private String nickName; @Field("is_available") private boolean isAvailable = true; @Field("is_public") private boolean isPublic; @Field("create_at") private Date createAt; @Field("last_activity_at") private Date lastActivityAt; @Field("web_url") private String webUrl; @Field("repo_url") private String repoUrl; @Field("avatar_url") private String avatarUrl; private User owner; @Indexed private long stars; private Map<String, Collection<String>> categories; private Collection<ProjectMember> members; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public boolean getIsAvailable() { return isAvailable; } public void setIsAvailable(boolean available) { isAvailable = available; } public boolean getIsPublic() { return isPublic; } public void setIsPublic(boolean aPublic) { isPublic = aPublic; } public Date getCreateAt() { return createAt; } public void setCreateAt(Date createAt) { this.createAt = createAt; } public Date getLastActivityAt() { return lastActivityAt; } public void setLastActivityAt(Date lastActivityAt) { this.lastActivityAt = lastActivityAt; } public String getWebUrl() { return webUrl; } public void setWebUrl(String webUrl) { this.webUrl = webUrl; } public String getRepoUrl() { return repoUrl; } public void setRepoUrl(String repoUrl) { this.repoUrl = repoUrl; } public String getAvatarUrl() { return avatarUrl; } public void setAvatarUrl(String avatarUrl) { this.avatarUrl = avatarUrl; } public Map<String, Collection<String>> getCategories() { return categories; } public void setCategories(Map<String, Collection<String>> categories) { this.categories = categories; } public User getOwner() { return owner; } public void setOwner(User owner) { this.owner = owner; } public long getStars() { return stars; } public void setStars(long stars) { this.stars = stars; } public Collection<ProjectMember> getMembers() { return members; } public void setMembers(Collection<ProjectMember> members) { this.members = members; } public String getNickName() { return nickName; } public void setNickName(String nickName) { this.nickName = nickName; } }
主要涉及到的表:
项目基本信息(project_info)
{
"id":"",//主键
"name":"", //名称
"description":"",//描述
"is_available":false,//是否可用
"is_public":false, //是否公开
"create_at":"", //项目创建时间
"last_activity_at":"", //最后一次更新时间
"is_starred_by_current_user":false,
"owner":{ //拥有者
"id":"", //拥有者id,uc的user_id
"name":"", //拥有者的名字
"user_name":"" //拥有者的工号
},
"stars" : NumberLong(0),
"web_url":"", //项目首页地址,预留
"repo_url":"", //仓库地址,gitlab or svn
"avatar_url":"", //项目logo
"categories":{ //项目所属类别
"language":[], //编程语言
"type":[], //项目所属类别 web or 组件
"sub_type":[], //项目所属子类别 web应用 移动应用 web组件 ios组件 android组件
"tag":[] //项目标签
},
"members":[ //项目成员
{
"id":"", //拥有者id,uc的user_id
"name":"", //项目成员姓名
"user_name":"", //项目成员工号
"role":"" //项目成员角色,如:主程,开发者,策划,测试
}
]
}维度(dimension)
{ "id":"",//主键 "value":"language", //维度值:type/sub_type/tag/language "text":"编程语言" //维度显示文本 }项目被star记录(project_star_record)
{ "id":"", //主键 "project_id":"", //关联project_info的id "user_id":"", //用户id "star_time":"", // 项目被star的时间 }
相关文章推荐
- CharSequence类型
- 浅析 - Android异步操作
- CPU的散热与选购
- 马哥第四周作业
- Web安全测试之跨站请求伪造(CSRF)篇
- 哈希 /java初学
- 389. Find the Difference
- Guess the Number
- Activiti之eclipse插件安装
- 【Codeforces Round #351 Div. 2】 673A Bear and Game
- 神侃:反向激励能救活多少APP?
- alpha测试和beta测试的区别是什么?
- Activiti之eclipse插件安装
- 图中最短路径算法(Dijkstra算法)(转)
- PHP内核之Apache的PHP模块启动
- java : 打包导出 json.jar
- MFC可编辑列表框控件功能实现
- 面向对象_static的注意事项
- [linux]jenkins迁移
- 【Spring实战】--1Spring的核心