@big-bear
2016-02-25T17:20:20.000000Z
字数 12403
阅读 1319
hibernate
默认情况下,查询结果应该按照其和查询条件间的相关度进行排序。关于相关度排序,会在后续的文章中介绍。
但是我们也能够不再使用相关度作为排序的依据,转而我们可以使用日期,数值类型甚至字符串的顺序作为排序依据。比如,对App的搜索结果,我们可以使用其名字在字母表中的顺序进行排序。
为了支持对于某个域的排序,我们需要向索引中添加一些必要的信息。在对字符串类型的域进行索引时,默认的分析器会将该域的值进行分词,所以对于某个值“Hello World”,在索引中会有两个入口对“Hello”和“World”进行单独保存。这样做能够让查询更具效率,但是当我们需要对该域进行排序时,分词器是不需要的。
因此,我们可以对该域设置两个@Field注解:
@Column@Fields({@Field,@Field(name="sorting_name", analyze=Analyze.NO)})private String name;
一个用来建立标准的索引,一个用来建立用于排序的索引,其中指定了analyze=Analyze.NO,默认情况下分词器是被使用的。
这个域就可以被用来创建Lucene的SortField对象,并集合FullTextQuery使用:
import org.apache.lucene.search.Sort;import org.apache.lucene.search.SortField;// ...Sort sort = new Sort(new SortField("sorting_name", SortField.STRING));hibernateQuery.setSort(sort); // a FullTextQuery object
执行此查询后,得到的结果会按照App名字,从A-Z进行排序。 实际上,SortField还能够接受第三个boolean类型的参数,当传入true时,排序结果会被颠倒即从Z-A。
错误:org.hibernate.search.SearchException: Try to search with an empty string: title
hibernate search不支持传入空值的 传入空值会报错
相同错误参考
hibernate search -- 多条件查询
参考地址代码
public Query BuildQuery(Class<?> type, String category, String degree, String city, String keyWords, Long domainId,String[] fileds) {FullTextSession fullTextSession = Search.getFullTextSession(this.gqFactory.getSession());QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(type).get();org.apache.lucene.search.Query luceneQuery = null;MustJunction term = qb.bool().must(qb.keyword().onFields(fileds).matching(keyWords).createQuery());if (StringUtils.isNotBlank(city)) {term.must(qb.keyword().onField("location").matching(city).createQuery());}if (StringUtils.isNotBlank(degree)) {term.must(qb.keyword().onField("degree").matching(degree).createQuery());}if (StringUtils.isNotBlank(category)) {term.must(qb.keyword().onField("category").matching(category).createQuery());}luceneQuery = term.createQuery();System.out.println(luceneQuery.toString());FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(luceneQuery, type);return fullTextQuery;}
实现的测试代码:
实体1:
package com.wisdombud.wisdomhr.pojo.job;import java.util.Date;import java.util.Set;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.JoinColumn;import javax.persistence.JoinTable;import javax.persistence.ManyToMany;import javax.persistence.Table;import javax.persistence.Temporal;import javax.persistence.TemporalType;import org.hibernate.search.annotations.Field;import org.hibernate.search.annotations.Fields;import org.hibernate.search.annotations.Index;import org.hibernate.search.annotations.Indexed;import org.hibernate.search.annotations.IndexedEmbedded;import org.hibernate.search.annotations.Store;import org.springframework.format.annotation.DateTimeFormat;import com.fasterxml.jackson.annotation.JsonFormat;import com.wisdombud.constants.Constants;import com.wisdombud.wisdomhr.pojo.dic.DicJoBDomain;/*** 功能: 职位表.<br/>* date: 2015年08月09日 10:59 <br/>** @author joseph* @version*//*** @author wgzuo*/@Entity@Table(name = "BASE_JOB")@Indexed(index = "indexes/job")public class BaseJob extends com.wisdombud.pojo.UuidEntity {private static final long serialVersionUID = 1L;@Column(name = "CARRER_ID")private String carrerId;@Column(name = "SPIDER_JOB_ID")private String spiderJobId;/*** 标题**/@Column(name = "TITLE")@Field(name = "title", index = Index.TOKENIZED, store = Store.YES)private String title;/*** 1:全职2:实习**/@Column(name = "CATEGORY")@Field(name = "category", index = Index.TOKENIZED, store = Store.YES)private String category;/*** 就业系统中的ID*/@Column(name = "ENTERPRISE_CARRER_ID")private String enterpriseCarrerId;/*** 企业ID,如果有该ID 表示该职位是由企业发的**/@Column(name = "ENTERPRISE_ID")private String enterpriseId;/*** 企业名称**/@Column(name = "ENTERPRISE_NAME")@Field(name = "enterpriseName", index = Index.TOKENIZED, store = Store.YES)private String enterpriseName;@Column(name = "ENTERPRISE_LOGO")private String enterpriseLogo = Constants.ENTERPRISE_DEFAULT_PORTAIT; ;// 默认的logo;/*** 企业所属行业**/@Column(name = "ENTERPRISE_INDUSTRY")private String enterpriseIndustry;/*** 企业性质**/@Column(name = "ENTERPRISE_NATURE")private String enterpriseNature;/*** 工作城市,**/@Column(name = "LOCATION")@Field(name = "location", index = Index.TOKENIZED, store = Store.YES)private String location;/*** 学历要求,以“,”分隔的学历id1:大专及以上2:本科及以上3:硕士及以上4:博士**/@Field(name = "degree", index = Index.TOKENIZED, store = Store.YES)@Column(name = "DEGREE")private String degree;/*** 工资**/@Column(name = "SALARY")private String salary;/*** 阅读次数**/@Column(name = "VIEW_COUNT")private Integer viewCount = 0;@Column(name = "DELIVER_COUNT")private Integer deliverCount = 0;/*** 收藏次数**/@Column(name = "FAVORITE_COUNT")private Integer favoriteCount = 0;/*** 点赞数量**/@Column(name = "LIKE_COUNT")private Integer likeCount = 0;/*** 投递简历数量**/@Column(name = "RESUME_COUNT")private Integer resumeCount = 0;/*** 详细工作地址**/@Column(name = "ADDRESS")@Field(name = "address", index = Index.TOKENIZED, store = Store.YES)private String address;/*** hotWeight:热门排行权重.** @since JDK 1.8*/@Fields({ @Field, @Field(name = "hotWeight", index = Index.UN_TOKENIZED) })@Column(name = "HOT_WEIGHT")private Long hotWeight;/*** spreadLevel:推广级别,0是没有推广,1是最低级别** @since JDK 1.8*/@Column(name = "SPREAD_LEVEL")private Integer spreadLevel = 0;/*** invitationLevel:邀约级别,0是没有邀约,1是最低级别** @since JDK 1.8*/@Column(name = "INVITATION_LEVEL")private Integer invitationLevel = 0;/*** 0:无效1:有效2:举报处理中**/@Column(name = "STATUS")private Integer status = 1;/*** 举报ID**/@Column(name = "ACCUSATION_ID")private String accusationId;/*** 来源**/@Column(name = "SOURCE")private String source;@javax.persistence.Transientprivate String content;/*** 下线时间**/@JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Shanghai")@DateTimeFormat(pattern = "yyyy-MM-dd")@Temporal(TemporalType.TIMESTAMP)@Column(name = "OFFLINE_TIME")protected Date offLineTime;/*** 激活时间**/@JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Shanghai")@DateTimeFormat(pattern = "yyyy-MM-dd")@Temporal(TemporalType.TIMESTAMP)@Column(name = "ACTIVATE_TIME")protected Date activateTime;/*** 是否加V 0不加V 1加V**/@javax.persistence.Transientprivate Integer isVerify;/*** 是否有圈子的标记*/// @Field(name = "domainId", index = Index.UN_TOKENIZED, store = Store.YES)@Column(name = "HAS_DOMAIN")private Integer hasDomain = 0;@ManyToMany@JoinTable(name = "H_REL_JOB_DOMAIN", joinColumns = { @JoinColumn(name = "JOB_ID") }, inverseJoinColumns = { @JoinColumn(name = "DOMAIN_ID") })@IndexedEmbeddedprivate Set<DicJoBDomain> domains;public String getCarrerId() {return carrerId;}public void setCarrerId(String carrerId) {this.carrerId = carrerId;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getCategory() {return category;}public void setCategory(String category) {this.category = category;}public String getEnterpriseCarrerId() {return enterpriseCarrerId;}public void setEnterpriseCarrerId(String enterpriseCarrerId) {this.enterpriseCarrerId = enterpriseCarrerId;}public String getEnterpriseId() {return enterpriseId;}public void setEnterpriseId(String enterpriseId) {this.enterpriseId = enterpriseId;}public String getEnterpriseName() {return enterpriseName;}public void setEnterpriseName(String enterpriseName) {this.enterpriseName = enterpriseName;}public String getEnterpriseIndustry() {return enterpriseIndustry;}public void setEnterpriseIndustry(String enterpriseIndustry) {this.enterpriseIndustry = enterpriseIndustry;}public String getEnterpriseNature() {return enterpriseNature;}public void setEnterpriseNature(String enterpriseNature) {this.enterpriseNature = enterpriseNature;}public String getLocation() {return location;}public void setLocation(String location) {this.location = location;}public String getDegree() {return degree;}public void setDegree(String degree) {this.degree = degree;}public String getSalary() {return salary;}public void setSalary(String salary) {this.salary = salary;}public Integer getViewCount() {if (viewCount == null) {return 0;}return viewCount;}public void setViewCount(Integer viewCount) {this.viewCount = viewCount;}public Integer getFavoriteCount() {if (favoriteCount == null) {return 0;}return favoriteCount;}public void setFavoriteCount(Integer favoriteCount) {this.favoriteCount = favoriteCount;}public Integer getDeliverCount() {if (deliverCount == null) {return 0;}return deliverCount;}public void setDeliverCount(Integer deliverCount) {this.deliverCount = deliverCount;}public Integer getLikeCount() {if (likeCount == null) {return 0;}return likeCount;}public void setLikeCount(Integer likeCount) {this.likeCount = likeCount;}public Integer getResumeCount() {if (resumeCount == null) {return 0;}return resumeCount;}public void setResumeCount(Integer resumeCount) {this.resumeCount = resumeCount;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public Long getHotWeight() {if (hotWeight == null) {return 0L;}return hotWeight;}public void setHotWeight(Long hotWeight) {this.hotWeight = hotWeight;}public Integer getSpreadLevel() {return spreadLevel;}public void setSpreadLevel(Integer spreadLevel) {this.spreadLevel = spreadLevel;}public Integer getInvitationLevel() {return invitationLevel;}public void setInvitationLevel(Integer invitationLevel) {this.invitationLevel = invitationLevel;}public String getSource() {return source;}public void setSource(String source) {this.source = source;}public Integer getStatus() {return status;}public void setStatus(Integer status) {this.status = status;}public String getAccusationId() {return accusationId;}public void setAccusationId(String accusationId) {this.accusationId = accusationId;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public String getEnterpriseLogo() {return enterpriseLogo;}public void setEnterpriseLogo(String enterpriseLogo) {this.enterpriseLogo = enterpriseLogo;}public Date getOffLineTime() {return offLineTime;}public void setOffLineTime(Date offLineTime) {this.offLineTime = offLineTime;}public Date getActivateTime() {return activateTime;}public void setActivateTime(Date activateTime) {this.activateTime = activateTime;}/*** @see java.lang.Object#hashCode()*/@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + ((this.id == null) ? 0 : id.hashCode());return result;}/*** @see java.lang.Object#equals(java.lang.Object)*/@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;BaseJob other = (BaseJob) obj;if (id == null) {if (other.id != null)return false;} else if (!id.equals(other.id))return false;return true;}public Integer getIsVerify() {return isVerify;}public String getSpiderJobId() {return spiderJobId;}public void setSpiderJobId(String spiderJobId) {this.spiderJobId = spiderJobId;}public void setIsVerify(Integer isVerify) {this.isVerify = isVerify;}public Integer getHasDomain() {return hasDomain;}public void setHasDomain(Integer hasDomain) {this.hasDomain = hasDomain;}public Set<DicJoBDomain> getDomains() {return domains;}public void setDomains(Set<DicJoBDomain> domains) {this.domains = domains;}}
实体2:
/*** Copyright (c) 2015, www.wisdombud.com* All Rights Reserved.*/package com.wisdombud.wisdomhr.pojo.dic;import java.util.Set;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.Id;import javax.persistence.ManyToMany;import javax.persistence.Table;import com.wisdombud.wisdomhr.pojo.job.BaseJob;/*** 功能: 职位圈子实体.<br/>* date: 2015年12月21日 下午3:35:45 <br/>** @author ytche@wisdombud.com* @version* @since JDK 1.8*/@Entity@Table(name = "DIC_JOB_DOMAIN")public class DicJoBDomain {@Idprivate Long id;@Column(name = "NAME")private String name;@ManyToMany(mappedBy = "domains")private Set<BaseJob> baseJobs;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Set<BaseJob> getBaseJobs() {return baseJobs;}public void setBaseJobs(Set<BaseJob> baseJobs) {this.baseJobs = baseJobs;}}
srv方法:
import org.apache.commons.lang.StringUtils;import org.hibernate.Query;import org.hibernate.search.FullTextQuery;import org.hibernate.search.FullTextSession;import org.hibernate.search.Search;import org.hibernate.search.query.dsl.MustJunction;import org.hibernate.search.query.dsl.QueryBuilder;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.wisdombud.dao.GeneralQueryFactory;public Query testIndexedEmbedded(Class<?> type) {FullTextSession fullTextSession = Search.getFullTextSession(this.gqFactory.getSession());QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(type).get();org.apache.lucene.search.Query luceneQuery = qb.keyword().onFields("domains.id").matching("1").createQuery();FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(luceneQuery, type);return fullTextQuery;}
test方法
public class lianchaTest extends AbstractTransactionContextTest {@AutowiredJobSearch jobSearch;@Testpublic void test() {Query query = this.jobSearch.testIndexedEmbedded(BaseJob.class);List<BaseJob> baseJobs = query.list();System.out.println(baseJobs.size() + "--------");}}