zoukankan      html  css  js  c++  java
  • solr6.6 高级搜索Facet

      1、介绍

        facet分面查询是solr中以导航为目的的查询,在用户查询的结果上根据分类增加了count信息,然后用户根据count信息做进一步实现渐进式精确搜索。

        什么字段适合用facet呢?     

        facet中适宜的字段一般代表某个实体的公共属性,比如品牌、型号、价格区间、作者、厂商、书籍出版商等。

        Facet 字段的要求有什么要求呢?

        Facet 的字段必须被索引 . 一般来说该字段无需分词 , 无需存储 。

        无需分词是因为该字段的值代表了一个整体概念 , 如电脑的品牌 ” 联想 ” 代表了一个整体概念 , 如果拆成 ” 联 ”,” 想 ” 两个字都不具有实际意义 . 另外该字段的值无需进行大小写转换等处理 , 保持其原貌即可 。

        无需存储是因为一般而言用户所关心的并不是该字段的具体值 , 而是作为对查询结果进行分组的一种手段 , 用户一般会沿着这个分组进一步深入搜索 。

        对于文本(text)字段, 如果包含分词等处理,处理后的term可能不是你想要的。如果你想要solr对文本字段既分析(搜索),又做分面处理,使用copyField对字段创建两个版本:一个Text和一个String。

        比如 CPU 类型 ”Intel 酷睿 2 双核 P7570”,拆分成 ”Intel”,” 酷睿 ”,”P7570” 这样一些关键字并分别索引 , 可能提供更好的搜索体验 . 但是如果将 CPU 作为 Facet 字段 , 最好不进行分词 . 这样就造成了矛盾 ,

         解决方法为 ,将 CPU 字段设置为不分词不存储 , 然后建立另外一个字段为它的 COPY, 对这个 COPY 的字段进行分词和存储 。

        在managed-schema文件中:

        

      2、建立内核,索引数据

        建立内核:  solr create -c mycore

        导入数据,将solr-6.6.0exampleexampledocs文件夹下的文件导入:  java -jar -Dc=mycore -Dauto post.jar ..exampleexampledocs*

        

      3、分面查询测试

       3.1、Field-value Faceting

        主要参数:

             facet.field :指定字段

             facet=true 该参数设置为true,分面查询才能起作用

             facet.field: 标识一个字段被视为一个方面,可以设置多个字段

             facet.mincount:在分面值返回之前设置必须出现的最小文档数,默认情况下,当前搜索中没有匹配的结果的词项会包含在分面结果中。

                     因此通常将facet.mincount至少设置为1, 默认值0

                facet.missing:  如果设置为true, 会返回匹配查询但没有facet的所有结果的计数。默认为false.

             facet.contains:  限制分面term为包含指定子串(substring)

             facet.prefix  :限制分面term为指定前缀。

             facet.contains.ignoreCase:使用facet.contains和facet.prefix时,忽略子串大小写,默认是是false,不忽略大小写,true:忽略大小写

             facet.limit:此参数指定应该为方面字段返回的约束计数的最大数量(基本上是返回的字段的构面数)。 负值意味着Solr将返回无限数量的约束计数。默认值是100。

             facet.sort:  count 按计数排序,最高的在前。index 按字符顺序。默认是按照count 按计数排序

             

        例如查询:

        http://localhost:8983/solr/mycore/select?q=*:*&fl=id,name,price&facet=true&facet.field=cat

        

        http://localhost:8983/solr/mycore/select?q=price:[0 TO 10]&fl=id,name,price,author&facet=true&facet.field=cat

        

        facet.mincount=2

        http://localhost:8983/solr/mycore/select?q=price:[0 TO 10]&fl=id,name,price,author&facet=true&facet.field=cat&facet.mincount=2

        结果:

        

        facet.contains =el

        http://localhost:8983/solr/mycore/select?q=price:[0 TO 10]&fl=id,name,price,author&facet=true&facet.field=cat&facet.contains =el

        结果:

        

        facet.contains =the&facet.contains.ignoreCase=true 

         http://localhost:8983/solr/mycore/select?q=price:[0 TO 10]&fl=id,name,price,author&facet=true&facet.field=name&facet.contains =the

        结果:

        

        http://localhost:8983/solr/mycore/select?q=price:[0 TO 10]&fl=id,name,price,author&facet=true&facet.field=name&facet.contains =the&facet.contains.ignoreCase=true

        结果:

        

         facet.prefix =The

        http://localhost:8983/solr/mycore/select?q=price:[0 TO 10]&fl=id,name,price,author&facet=true&facet.field=name&facet.prefix =The

        结果:

        

        facet.limit =2 只返回两条

        http://localhost:8983/solr/mycore/select?q=price:[0 TO 10]&fl=id,name,price,author&facet=true&facet.field=name&facet.limit =2

        结果:

        

        facet.sort =count

        http://localhost:8983/solr/mycore/select?q=price:[0 TO 10]&fl=id,name,price,author&facet=true&facet.field=cat&facet.sort =count

        的结果和

        http://localhost:8983/solr/mycore/select?q=price:[0 TO 10]&fl=id,name,price,author&facet=true&facet.field=cat

        一样

        

        facet.sort =index 

        http://localhost:8983/solr/mycore/select?q=price:[0 TO 10]&fl=id,name,price,author&facet=true&facet.field=cat&facet.sort =index

        按字符顺序

        

        

        http://localhost:8983/solr/mycore/select?q=*:*&fl=id,name,price&facet=true&facet.field=cat&facet.field=genre_s

        

      3.2、key 操作符

        可以用 key 操作符为 Facet 字段取一个别名 :

        &facet.field={!key=猫}cat

        http://localhost:8983/solr/mycore/select?q=*:*&fl=id,name,price&facet=true&facet.field={!key=猫}cat

        查询结果:

        

      3.3、 tag 操作符和 ex 操作符

        当查询使用 filter query 的时候 , 如果 filter query 的字段正好是 Facet 字段 , 那么查询结果往往被限制在某一个值内 

        &fq=cat:currency

        &facet=true

        &facet.field=cat

        http://localhost:8983/solr/mycore/select?q=*:*&fl=id,name,price&facet=true&facet.field=cat&fq=cat:currency

        返回结果:

        

        可以看到 , cat值 为 currency的产品共有 4件 , 其它的数目都是0, 这是因为在 filter 里已经限制了 cat:currency. 这样 , 查询结果中 , 除了 cat = currency 的这一项之外 , 其它项目没有实际的意义 .

        有些时候 , 用户希望把结果限制在某一范围内 , 又希望查看该范围外的概况 . 比如上述情况 ,既要把查询结果限制在 cat = currency的数据 , 又想查看一下其它类型的有多少产品 . 这个时候需要用到 tag 和 ex 操作符 .

        tag 就是把一个 filter 标记起来 ,ex(exclude) 是在 Facet 的时候把标记过的 filter 排除在外 .

        例 :

        &fq={!tag=aa}cat:currency

        &facet=true

        &facet.field={!ex=aa}cat

        http://localhost:8983/solr/mycore/select?q=*:*&fl=id,name,price&facet=true&facet.field={!ex=aa}cat&fq={!tag=aa}cat:currency

        返回结果:

        

       

      3.4、Range Faceting

        主要参数:

            facet.range: 指定字段

            facet.range.start:区间开始值

            facet.range.end: 区间结束值

            facet.range.gap:步长

            - facet.range
            facet.range=price&facet.range=age
            facet.range=lastModified_dt

            - facet.range.start
            f.price.facet.range.start=0.0&f.age.facet.range.start=10
            f.lastModified_dt.facet.range.start=NOW/DAY-30DAYS

            - facet.range.end
            f.price.facet.range.end=1000.0&f.age.facet.range.start=99
            f.lastModified_dt.facet.range.end=NOW/DAY+30DAYS

            - facet.range.gap
            f.price.facet.range.gap=100&f.age.facet.range.gap=10
            f.lastModified_dt.facet.range.gap=+1DAY

        http://localhost:8983/solr/mycore/select?q=*:*&fl=id,name,price&facet=true&facet.range=price&f.price.facet.range.start=0.0&f.price.facet.range.end=1000.0&f.price.facet.range.gap=100

         

      

      3.5、Interval Faceting

        主要参数:

            facet.interval:指定字段

            facet.interval.set: 间隔设置

        http://localhost:8983/solr/mycore/select?q=*:*&fl=id,name,price&facet=true&facet.interval=price&f.price.facet.interval.set=[0,10]&f.price.facet.interval.set=(10,100]&f.price.facet.interval.set=(100,200]

        

        

       java实现代码:

    import org.apache.solr.client.solrj.SolrClient;
    import org.apache.solr.client.solrj.SolrQuery;
    import org.apache.solr.client.solrj.SolrServerException;
    import org.apache.solr.client.solrj.impl.HttpSolrClient;
    import org.apache.solr.client.solrj.response.FacetField;
    import org.apache.solr.client.solrj.response.IntervalFacet;
    import org.apache.solr.client.solrj.response.QueryResponse;
    import org.apache.solr.client.solrj.response.RangeFacet;
    
    import java.io.IOException;
    import java.util.List;
    
    /**
     * @Author:sks
     * @Description:
     * @Date:Created in 15:38 2017/12/21
     * @Modified by:
     **/
    public class facet {
    
        private static SolrClient solr;
    
        /**
         * @Author:sks
         * @Description:初始化solr客户端
         * @Date:
         */
        public static void Init(String urlString){
    
            solr = new HttpSolrClient.Builder(urlString).build();
        }
    
        /**
        * @Author:sks
        * @Description:分面查询,别名
        * @Date:
        */
        private static void FacetSearch() throws SolrServerException,IOException {
            SolrQuery params = new SolrQuery();
            params.setQuery("*:*");
            params.setFields("id,name,price");
            params.setParam("omitHeader",true);//隐藏responseHeader
            params.setFacet(true);//设置facet=on
    //        params.addFacetField(new String[] { "{!key=猫}cat","genre_s" }); //给cat别名
            params.addFacetField(new String[] { "cat","genre_s" });
            QueryResponse queryResponse = solr.query(params);
            List<FacetField> list = queryResponse.getFacetFields();
            for (FacetField ff:list){
                System.out.println(ff.getName());
                List<FacetField.Count> lc = ff.getValues();
                for (FacetField.Count fc:lc){
                    System.out.println("    "+fc.getName()+": "+fc.getCount());
                }
            }
        }
        
        /**
        * @Author:sks
        * @Description:分面查询,运用fq,tag,ex操作符
        * @Date: 
        */
        private static void FacetFqTagExSearch() throws SolrServerException,IOException {
            SolrQuery params = new SolrQuery();
            params.setQuery("*:*");
            params.setFacet(true);
            params.setFields("id,name,price");
            params.setParam("omitHeader",true);//隐藏responseHeader
            params.setParam("fq","{!tag=aa}cat:currency");
            params.addFacetField(new String[] { "{!ex=aa}cat" });
    
            QueryResponse queryResponse = solr.query(params);
            List<FacetField> list = queryResponse.getFacetFields();
            for (FacetField ff:list){
                System.out.println(ff.getName());
                List<FacetField.Count> lc = ff.getValues();
                for (FacetField.Count fc:lc){
                    System.out.println("    "+fc.getName()+": "+fc.getCount());
                }
            }
        }
    
    
    
        /**
        * @Author:sks
        * @Description:范围分面查询
        * @Date:
        */
        private static void FacetRangeSearch() throws SolrServerException,IOException {
            SolrQuery params = new SolrQuery();
            params.setQuery("*:*");
            params.setFields("id,name,price");
            params.setParam("omitHeader",true);//隐藏responseHeader
            params.setFacet(true);//设置facet=on
    //        params.addFacetField(new String[] { "cat","genre_s" });//设置需要facet的字段
            String field = "price";
            double start = 0;
            double end = 1000;
            double gap = 100;
            params.addNumericRangeFacet(field,start,end,gap);
    
            QueryResponse queryResponse = solr.query(params);
            List<RangeFacet> list = queryResponse.getFacetRanges();
            for (RangeFacet ff:list){
                System.out.println(ff.getName());
                List<RangeFacet.Count> rclist = ff.getCounts();
                for(RangeFacet.Count rc: rclist){
                    System.out.println("    " + rc.getValue() + ": " + rc.getCount());
                }
    
            }
        }
    
    
        /**
        * @Author:sks
        * @Description:区间分面查询
        * @Date:
        */
        private static void FacetIntervalSearch() throws SolrServerException,IOException {
            SolrQuery params = new SolrQuery();
            params.setQuery("*:*");
            params.setFields("id,name,price");
            params.setParam("omitHeader",true);//隐藏responseHeader
            params.setFacet(true);
            String field = "price";
            String[] intervals = new String[] { "[0,10]","(10,100]" ,"(100,200]"};
            params.addIntervalFacets(field,intervals);
            QueryResponse queryResponse = solr.query(params);
            List<IntervalFacet> list = queryResponse.getIntervalFacets();
            for (IntervalFacet ff:list){
                System.out.println(ff.getField());
                List<IntervalFacet.Count> rclist = ff.getIntervals();
                for(IntervalFacet.Count ic: rclist){
                    System.out.println("    " + ic.getKey() + ": " + ic.getCount());
                }
            }
        }
        public static void main(String []args) throws SolrServerException, IOException {
    
            String urlString = "http://localhost:8983/solr/mycore";
            Init(urlString);
    //        FacetSearch();
            FacetFqTagExSearch();
    //        FacetRangeSearch();
    //        FacetIntervalSearch();
        }
    }

        

      参考资料:https://lucene.apache.org/solr/guide/6_6/faceting.html

  • 相关阅读:
    C# 通过 probing 指定 dll 寻找文件夹
    C# 通过 probing 指定 dll 寻找文件夹
    WPF 一个性能比较好的 gif 解析库
    WPF 一个性能比较好的 gif 解析库
    PowerShell 通过 WMI 获取系统安装的驱动
    PowerShell 通过 WMI 获取系统安装的驱动
    win10 uwp 好看的时间选择控件
    PHP ftp_ssl_connect() 函数
    PHP ftp_size() 函数
    PHP ftp_site() 函数
  • 原文地址:https://www.cnblogs.com/shaosks/p/8079048.html
Copyright © 2011-2022 走看看