# solr查询实例
# 一、方法说明
# 1.Solr的检索运算符
- “:” 指定字段查指定值,如返回所有值
*:*
- “?” 表示单个任意字符的通配
- “” 表示多个任意字符的通配(不能在检索的项开始使用或者?符号)
- “~” 表示模糊检索,如检索拼写类似于”roam”的项这样写:roam~将找到形如foam和roams的单词;roam~0.8,检索返回相似度在0.8以上的记录。
- AND、|| 布尔操作符
- OR、&& 布尔操作符
- NOT、!、-(排除操作符不能单独与项使用构成查询)
- “+” 存在操作符,要求符号”+”后的项必须在文档相应的域中存在
- ( ) 用于构成子查询
- [] 包含范围检索,如检索某时间段记录,包含头尾,date:[201507 TO 201510]
- {} 不包含范围检索,如检索某时间段记录,不包含头尾date:{201507 TO 201510}
# 2.Solr方法
- setQuery(String) 设置查询条件,相当于查询参数的q
- addFilterQuery(String) 添加过滤条件,相当于查询参数的fq
- addField(String) 设置返回字段
- setStart(Int) 设置查询开始条数
- setRows(Int) 设置查询条数
- setSort(String enum)设置排序功能,枚举用SolrQuery.ORDER.desc
(暂时只用到这些方法,剩下的欢迎补充)
注:setQuery和addFilterQuery方法本质上都是查询条件,但是addFilterQuery使用了缓存机制, 查询结果取setQuery和addFilterQuery的交集。 将常用过滤条件设置到addFilterQuery方法中,这样能减少了查询过程的IO操作, 又能控制缓存的容量不会消耗过多的内存。
参考地址 :https://blog.csdn.net/kuyuyingzi/article/details/17651451 (opens new window)
# 二、具体实例
# 1.以查询待竞价结果为例
//注入SolrClient查询solr,配置方法请查看[使用docker 搭建solr集群]
@Autowired
SolrClient solrClient;
public Page<WaitingBidDto> getPage(BaseVo<SearchBidDto> dto) throws ServiceException {
SearchBidDto searchDto = dto.getCondition();
//创建查询
SolrQuery query = new SolrQuery();
//设置查询条件(权限)
//截标时间在当前时间之后(NOW为当前时间)
//query.setQuery("endBidtime:[NOW TO *]");
//并列查询用AND
query.setQuery("currentProcee:BIDDING AND endBidtime:[2018-01-01T23:59:59.999Z TO *]");
//过滤掉被限制的高校单子
setFilter(query);
//过滤查询结果(筛选)
if (searchDto != null){
//申购单查询
if (!StringUtils.isEmpty(searchDto.getOrderCode())){
query.setQuery("orderCode:*"+searchDto.getOrderCode()+"*");
}
//申购主题查询
if (!StringUtils.isEmpty(searchDto.getOrderTitle())){
query.setQuery("orderTitle:*"+searchDto.getOrderTitle()+"*");
}
//申购单位查询
if (!StringUtils.isEmpty(searchDto.getOrderUnit())){
query.setQuery("orderUnit:*"+searchDto.getOrderUnit()+"*");
}
//设置收藏/忽略/关注高校等信息
if (!StringUtils.isEmpty(searchDto.getType())){
if ("A".equals(searchDto.getType())){
//关注高校
List<String> collegeList = attentionDao.getCollegeId(searchDto.getType());
query.setQuery(QueryUtil.orJoint("collegeId",collegeList));
}else {
//收藏/忽略的申购单
List<String> mainList = enshrineDao.getMainId(searchDto.getType());
query.setQuery(QueryUtil.orJoint("orderMainId",mainList));
}
}
}
//设置分页查询
//由于当前页和每页行数都是long类型,而setStart和setRows的参数为int类型,故需要进行强转
query.setStart((dto.getCurrent().intValue() - 1) * dto.getSize().intValue());
query.setRows(dto.getSize().intValue());
//设置排序(根据结束时间降序)
query.setSort("endBidtime", SolrQuery.ORDER.desc);
//接收结果集
QueryResponse res = null;
try {
//输入查询结果集和查询条件
res = solrClient.query("coOrderMain", query);
} catch (SolrServerException e) {
throw new ServiceException("solr查询错误");
} catch (IOException e) {
throw new ServiceException("传输信息错误");
}
//查询到的记录总数
long totalRow = res.getResults().getNumFound();
//查询结果集
List<WaitingBidDto> list = res.getBeans(WaitingBidDto.class);
//填充page对象
Page<WaitingBidDto> page = new Page<>(dto.getCurrent(), dto.getSize(), totalRow);
page.setRecords(list);
return page;
}
# 2.QueryUtil工具类(主要集成in和not in方法)
//or拼接,相当于in
public static String in(String fieldName, List<String> joinList){
if (joinList.size()>0){
StringBuffer sb = new StringBuffer(fieldName+":(");
for (String str:joinList){
sb.append(str).append(" OR ");
}
//拼接完删除最后的OR并加上")"
sb.replace(sb.length()-4,sb.length(),")");
return sb.toString();
}
return "";
}
//not and拼接,相当于not in
public static String notIn(String fieldName, List<String> joinList) {
if (joinList.size()>0){
StringBuffer sb = new StringBuffer("-"+fieldName+":(");
for (String str:joinList){
sb.append(str).append(" AND ");
}
//拼接完删除最后的OR并加上")"
sb.replace(sb.length()-5,sb.length(),")");
return sb.toString();
}
return "";
}
拼接结果 orJoint:MainId:(asd OR zxc OR qwe) 此语句是 (MainId:asd OR MainId:zxc OR MainId:qwe)的简化 notIn:-MainId:(asd OR zxc OR qwe)
# 3.solr拼接
{!join fromIndex=从表 toIndex=主表 from=主表字段 to=从表字段} 从表过滤条件 案例(查询企业未发货的主单) {!join fromIndex=cpBidOrder toIndex=coOrderMain from=orderMainId to=orderMainId} companyId:241336949 AND bidStatus:Y AND isDelivered:0 注意
- 连接查询条件需要放在fq中进行查询,若放在q中,则不能填写主表过滤条件
# 4.注意点
- 查询时使用的字段名为solr的字段名而非数据库字段名
- QueryResponse.getBeans(Class
type)方法只会给添加了@Field注解的字段赋值 - 查询语句orderCode:CB100012018003188 中的*可以匹配0个字符, 与mysql中的%必须匹配到1个以上字符不一样