[原]Lucene系列-facet

标签: | 发表时间:2015-01-09 23:42 | 作者:whuqin
出处:http://blog.csdn.net/whuqin

1.facet的直观认识

facet:面、切面、方面。个人理解就是维度,在满足query的前提下,观察结果在各维度上的分布(一个维度下各子类的数目)。

如jd上搜“手机”,得到4009个商品。其中品牌、网络、价格就是商品的维度(facet),点击某个品牌或者网络,获取更细分的结果。


点击品牌小米,获得小米手机的结果,显示27个。


点击移动4G,获得移动4G、小米手机,显示4个。


2.facet特性

  • facet counting:返回一个facet下某子类的结果数。如上面的品牌维度下小米子类中满足查询"手机"的结果有27个。
  • facet associations:一个文档与某子类的关联度,如一本书30%讲lucene,70%讲solor,这个百分比就是书与分类的关联度(匹配度、信心度)。
  • multiple facet requests:支持多facet查询(多维度查询)。如查询品牌为小米、网络为移动4G的手机。

3.实例

一个facet简单使用例子,依赖于lucene-facet-4.10.0。讲述了从搜手机到品牌、到网络向下browser的过程。

public class SimpleFacetsExample {
    private final Directory indexDir = new RAMDirectory();
    private final Directory taxoDir = new RAMDirectory();
    private final FacetsConfig config = new FacetsConfig();

    /** Empty constructor */
    public SimpleFacetsExample() {
        config.setHierarchical("Publish Date", true);
    }

    /** Build the example index. */
    private void index() throws IOException {
        IndexWriter indexWriter = new IndexWriter(indexDir, new IndexWriterConfig(Version.LUCENE_4_10_0,
                new WhitespaceAnalyzer()));
        // Writes facet ords to a separate directory from the main index
        DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);

        Document doc = new Document();
        doc.add(new TextField("device", "手机", Field.Store.YES));
        doc.add(new TextField("name", "米1", Field.Store.YES));
        doc.add(new FacetField("brand", "小米"));
        doc.add(new FacetField("network", "移动4G"));
        indexWriter.addDocument(config.build(taxoWriter, doc));

        doc = new Document();
        doc.add(new TextField("device", "手机", Field.Store.YES));
        doc.add(new TextField("name", "米4", Field.Store.YES));
        doc.add(new FacetField("brand", "小米"));
        doc.add(new FacetField("network", "联通4G"));
        indexWriter.addDocument(config.build(taxoWriter, doc));

        doc = new Document();
        doc.add(new TextField("device", "手机", Field.Store.YES));
        doc.add(new TextField("name", "荣耀6", Field.Store.YES));
        doc.add(new FacetField("brand", "华为"));
        doc.add(new FacetField("network", "移动4G"));
        indexWriter.addDocument(config.build(taxoWriter, doc));

        doc = new Document();
        doc.add(new TextField("device", "电视", Field.Store.YES));
        doc.add(new TextField("name", "小米电视2", Field.Store.YES));
        doc.add(new FacetField("brand", "小米"));
        indexWriter.addDocument(config.build(taxoWriter, doc));

        taxoWriter.close();
        indexWriter.close();
    }

    private void facetsWithSearch() throws IOException {
        DirectoryReader indexReader = DirectoryReader.open(indexDir);
        IndexSearcher searcher = new IndexSearcher(indexReader);
        TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir);

        FacetsCollector fc = new FacetsCollector();
        //1.查询手机
        System.out.println("-----手机-----");
        TermQuery query = new TermQuery(new Term("device", "手机"));
        FacetsCollector.search(searcher, query, 10, fc);
        Facets facets = new FastTaxonomyFacetCounts(taxoReader, config, fc);
        List<FacetResult> results = facets.getAllDims(10);
        //手机总共有3个,品牌维度:小米2个,华为1个;网络维度:移动4G 2个,联通4G 1个
        for (FacetResult tmp : results) {
            System.out.println(tmp);
        }
        //2.drill down,品牌选小米
        System.out.println("-----小米手机-----");
        DrillDownQuery drillDownQuery = new DrillDownQuery(config, query);
        drillDownQuery.add("brand", "小米");
        FacetsCollector fc1 = new FacetsCollector();//要new新collector,否则会累加
        FacetsCollector.search(searcher, drillDownQuery, 10, fc1);
        facets = new FastTaxonomyFacetCounts(taxoReader, config, fc1);
        results = facets.getAllDims(10);
        //获得小米手机的分布,总数2个,网络:移动4G 1个,联通4G 1个
        for (FacetResult tmp : results) {
            System.out.println(tmp);
        }

        //3.drill down,小米移动4G手机
        System.out.println("-----移动4G小米手机-----");
        drillDownQuery.add("network", "移动4G");
        FacetsCollector fc2 = new FacetsCollector();
        FacetsCollector.search(searcher, drillDownQuery, 10, fc2);
        facets = new FastTaxonomyFacetCounts(taxoReader, config, fc2);
        results = facets.getAllDims(10);
        for (FacetResult tmp : results) {
            System.out.println(tmp);
        }

        //4.drill sideways,横向浏览
        //如果已经进入了小米手机,但是还想看到其他牌子(华为)的手机数目,就用到了sideways
        System.out.println("-----小米手机drill sideways-----");
        DrillSideways ds = new DrillSideways(searcher, config, taxoReader);
        DrillDownQuery drillDownQuery1 = new DrillDownQuery(config, query);
        drillDownQuery1.add("brand", "小米");
        DrillSidewaysResult result = ds.search(drillDownQuery1, 10);
        results = result.facets.getAllDims(10);
        for (FacetResult tmp : results) {
            System.out.println(tmp);
        }

        indexReader.close();
        taxoReader.close();
    }

    /** Runs the search and drill-down examples and prints the results. */
    public static void main(String[] args) throws Exception {
        SimpleFacetsExample example = new SimpleFacetsExample();
        example.index();
        example.facetsWithSearch();
    }
}

输出:

-----手机-----
//总数3个,2个子类
dim=brand path=[] value=3 childCount=2
  小米 (2)
  华为 (1)

dim=network path=[] value=3 childCount=2
  移动4G (2)
  联通4G (1)

-----小米手机-----
//普通向下浏览,丢失了同一维度,其他子类的统计
dim=brand path=[] value=2 childCount=1
  小米 (2)

dim=network path=[] value=2 childCount=2
  移动4G (1)
  联通4G (1)

-----移动4G小米手机-----
dim=brand path=[] value=1 childCount=1
  小米 (1)

dim=network path=[] value=1 childCount=1
  移动4G (1)

-----小米手机drill sideways-----
//drill sideways, 保留了该drill维度的其他子类统计
dim=brand path=[] value=3 childCount=2
  小米 (2)
  华为 (1)
//小米手机中的网络分布
dim=network path=[] value=2 childCount=2
  移动4G (1)
  联通4G (1)

作者:whuqin 发表于2015/1/9 15:42:53 原文链接
阅读:205 评论:0 查看评论

相关 [lucene 系列 facet] 推荐:

[原]Lucene系列-facet

- - 文武天下
facet:面、切面、方面. 个人理解就是维度,在满足query的前提下,观察结果在各维度上的分布(一个维度下各子类的数目). 如jd上搜“手机”,得到4009个商品. 其中品牌、网络、价格就是商品的维度(facet),点击某个品牌或者网络,获取更细分的结果. 点击品牌小米,获得小米手机的结果,显示27个.

[原]Lucene系列-FieldCache

- - 文武天下
域缓存,加载所有文档中某个特定域的值到内存,便于随机存取该域值. 当用户需要访问各文档中某个域的值时,IndexSearcher.doc(docId)获得Document的所有域值,但访问速度比较慢,而且只能获得Stored域的值. FieldCache能获得域值数组,根据docId random access域值.

[原]Lucene系列-索引文件

- - 文武天下
本文介绍下lucene生成的索引有哪些文件组成,每个文件包含了什么信息. 基于Lucene 4.10.0. 索引(index)包含了存储的文档(document)正排、倒排信息,用于文本搜索. 索引又分为多个段(segments),每个新添加的doc都会存到一个新segment中,不同的segments又会合并成一个segment.

[原]Lucene系列-近实时搜索

- - 文武天下
近实时搜索(near-real-time)可以搜索IndexWriter还未commit的内容,介于immediate和eventual之间,在数据比较大、更新较频繁的情况下使用. lucene的nrt可以控制更新生效的间隔时间. 从indexwriter中获得indexreader. 建立indexsearcher.

solr中facet、group查询

- - 编程语言 - ITeye博客
项目(评论)中使用solr查询的时候,有个场景需求:. 1、获取某个商品下评论的级别数量统计(比如该商品下一到五颗星的评论数量各有多少);. 最终经过讨论,使用了solr中的group和facet完成. 先说下solr中保存的文档数据结构,如下:. .

跟益达学Solr5之Facet一瞥

- - 嘿↗你的益达
      Facet属于Solr的高级查询部分,之所以在还没有讲解普通Query之前,就开始更新Facet查询,是因为看到很多小伙伴都在为Facet而困扰,其实根本原因还是对Facet不理解. Facet英文单词本意是方面的意思,但在solr中Facet一般翻译为维度的意思,举个例子,学生可以按班级来分类,可以按性别来分类,可以身高来分类,可以按年龄来分类,可以按考试分数来分类,可以按兴趣爱好分类,可以按出生地址分类等等,上面所说的班级,性别,身高,年龄,考试分数,兴趣爱好,出生地址等等这些都是把学生进行归类分组的一个个维度.

Solr Facet技术的应用与研究

- - 美团技术团队
在 《搜索引擎关键字智能提示的一种实现》一文中介绍过,美团的CRM系统负责管理销售人员的门店(POI)和项目(DEAL)信息,提供统一的检索功能,其索引层采用的是SolrCloud. 在用户搜索时,如果能直观地给出每个品类的POI数目,各个状态的DEAL数目,可以更好地引导用户进行搜索,进而提升搜索体验.

lucene排序

- - 开源软件 - ITeye博客
排序是对于全文检索来言是一个必不可少的功能,在实际运用中,排序功能能在某些时候给我们带来很大的方便,比如在淘宝,京东等一些电商网站我们可能通过排序来快速找到价格最便宜的商品,或者通过排序来找到评论数最高或卖的最好的商品,再比如在Iteye里的博客栏里,每天都会以降序的方式,来显示出最新发出的几篇博客,有了排序,我们就能在某些时候很方便快速的得到某些有效信息,所以说排序功能,无处不在 ^_^.

Lucene 使用教程

- - 行业应用 - ITeye博客
1 lucene简介 . 1.1 什么是lucene . Lucene是一个全文搜索框架,而不是应用产品. 因此它并不像 http://www.baidu.com/ 或者google Desktop那么拿来就能用,它只是提供了一种工具让你能实现这些产品. 1.2 lucene能做什么 . 要回答这个问题,先要了解lucene的本质.

Lucene 4.x 之 IndexReader

- - zzm
在Lucene 3.x时代,《Lucene In Action》是一本相当不错的参考书,书中详细介绍了Lucene各种高级使用技术,对于开发者来说非常实用. 但是近期Lucene升级到了4.x版本,在性能等各方面有了很大的提高,值得在新项目中使用. 然而Lucene 4.x中的API相比3.x来说有了很大的改变,《Lucene In Action》中的很多内容都已经过时了,并且由于4.x推出的时间不长,还没有比较好的文档来对用法进行说明,这个系列文章就是想记录下自己使用Lucene 4.x的经验体会,供大家参考使用.