# 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个以上字符不一样
Last Updated: 7/26/2019, 9:53:21 AM