[solr] - Facet

Solr facet使用於分類統計,是最好的工具。下面例子使用facet將可模擬查詢搜索出租房信息。


 

1、在schema.xml中的內容如下:

複製代碼
<?xml version="1.0" ?>
<schema name="my core" version="1.1">

    <fieldtype name="string"  class="solr.StrField" sortMissingLast="true" omitNorms="true"/>
    <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
    <fieldType name="tdate" class="solr.TrieDateField" precisionStep="6" positionIncrementGap="0"/>
    <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
    <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
    <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
    <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
    <fieldtype name="binary" class="solr.BinaryField"/>
    <fieldType name="text_cn" class="solr.TextField">
        <analyzer type="index" class="org.wltea.analyzer.lucene.IKAnalyzer" />
        <analyzer type="query" class="org.wltea.analyzer.lucene.IKAnalyzer" />
        <analyzer>
            <tokenizer class="solr.KeywordTokenizerFactory"/>
            <filter class="solr.LowerCaseFilterFactory"/>
        </analyzer>
    </fieldType>
    
    <!-- general -->
    <field name="id" type="long" indexed="true" stored="true" multiValued="false" required="true"/>
    <field name="subject" type="text_cn" indexed="true" stored="true" />
    <field name="content" type="text_cn" indexed="true" stored="true" />
    <field name="regionId" type="int" indexed="true" stored="true" />
    <field name="region" type="text_cn" indexed="true" stored="true" />
    <field name="categoryId" type="int" indexed="true" stored="true" />
    <field name="category" type="text_cn" indexed="true" stored="true" />
    <field name="price" type="float" indexed="true" stored="true" />
    <field name="_version_" type="long" indexed="true" stored="true"/>
    
     <!-- field to use to determine and enforce document uniqueness. -->
     <uniqueKey>id</uniqueKey>

     <!-- field for the QueryParser to use when an explicit fieldname is absent -->
     <defaultSearchField>subject</defaultSearchField>

     <!-- SolrQueryParser configuration: defaultOperator="AND|OR" -->
     <solrQueryParser defaultOperator="OR"/>
</schema>
複製代碼

 

2、Java bean:

複製代碼
package com.my.entity;

import org.apache.solr.client.solrj.beans.Field;

public class Item {
    @Field
    private long id;
    @Field
    private String subject;
    @Field
    private String content;
    @Field
    private int regionId;
    @Field
    private int categoryId;
    @Field
    private float price;
    
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getSubject() {
        return subject;
    }
    public void setSubject(String subject) {
        this.subject = subject;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public int getRegionId() {
        return regionId;
    }
    public void setRegionId(int regionId) {
        this.regionId = regionId;
    }
    public int getCategoryId() {
        return categoryId;
    }
    public void setCategoryId(int categoryId) {
        this.categoryId = categoryId;
    }
    public float getPrice() {
        return price;
    }
    public void setPrice(float price) {
        this.price = price;
    }
}
複製代碼

 

3、使用solrj測試例子:

複製代碼
package com.my.solr;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrQuery.ORDER;
import org.apache.solr.client.solrj.SolrQuery.SortClause;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.impl.XMLResponseParser;
import org.apache.solr.client.solrj.response.FacetField;
import org.apache.solr.client.solrj.response.FacetField.Count;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.params.FacetParams;

import com.my.entity.Item;

public class TestSolr {
    private static HashMap<Integer, String> mapRegion = new HashMap<Integer, String>();
    private static HashMap<Integer, String> mapCategory = new HashMap<Integer, String>();

    public static void main(String[] args) throws IOException,
            SolrServerException {
        // ------------------------------------------------------
        // Set map
        // ------------------------------------------------------
        mapRegion.put(1, "羅湖區");
        mapRegion.put(2, "南山區");
        mapRegion.put(3, "龍崗區");
        mapRegion.put(4, "福田區");
        mapCategory.put(1, "單間");
        mapCategory.put(2, "2房1廳");
        mapCategory.put(3, "3房2廳");
        mapCategory.put(4, "1房1廳");
        
        String url = "http://localhost:8899/solr/mycore";
        HttpSolrServer core = new HttpSolrServer(url);
        core.setMaxRetries(1);
        core.setConnectionTimeout(5000);
        core.setParser(new XMLResponseParser()); // binary parser is used by
                                                    // default
        core.setSoTimeout(1000); // socket read timeout
        core.setDefaultMaxConnectionsPerHost(100);
        core.setMaxTotalConnections(100);
        core.setFollowRedirects(false); // defaults to false
        core.setAllowCompression(true);

        // ------------------------------------------------------
        // remove all data
        // ------------------------------------------------------
        core.deleteByQuery("*:*");
        List<Item> items = new ArrayList<Item>();
        items.add(makeItem(items.size() + 1, "龍城公寓一房一廳", "豪華城城公寓1房1廳,擰包入住", 1, 1, 1200f));
        items.add(makeItem(items.size() + 1, "興新宿舍樓 1室0廳", " 中等裝修 招女性合租", 1, 1, 1000f));
        items.add(makeItem(items.size() + 1, "西麗新屋村新宿舍樓單間", " 無敵裝修只招女性", 2, 1, 1000f));
        items.add(makeItem(items.size() + 1, "大芬村信和愛琴居地鐵口2房1廳", " 地鐵口 + 出行便利=居家首選", 3, 2, 2000f));
        items.add(makeItem(items.size() + 1, "龍崗富豪花園3房2廳出租", " 離地鐵口只要5分鐘,快來秒殺吧", 3, 3, 4500f));
        items.add(makeItem(items.size() + 1, "海景房園3房2廳出租", "無敵海景,可以看到倫敦", 4, 3, 8500f));
        items.add(makeItem(items.size() + 1, "天域花園1房1廳出租", "男女不限,入住免水電一月", 2, 4, 1500f));
        items.add(makeItem(items.size() + 1, "神一樣的漂亮,玉馨山莊3房2廳", "心動不如行動,擰包即可入住,來吧!", 1, 3, 9500f));
        items.add(makeItem(items.size() + 1, "玉馨山莊2房1廳,情侶最愛", "宅男宅女快來吧只要2500,走過路過,別再錯過", 1, 2, 2500f));
        items.add(makeItem(items.size() + 1, "天域花園3房2廳出租", "都來看看,都來瞄瞄,3房只要7500.", 4, 3, 7500f));
        items.add(makeItem(items.size() + 1, "深都花園出租3房2廳", "找愛乾淨的人氏,全新裝修", 4, 3, 5200f));
        core.addBeans(items);
        // commit
        core.commit();

        // ------------------------------------------------------
        // search
        // ------------------------------------------------------
        SolrQuery query = new SolrQuery();
        query.setQuery("*:*");
        query.setStart(0); // query的開始行數(分頁使用)
        query.setRows(100); // query的返回行數(分頁使用)
        query.setFacet(true); // 設置使用facet
        query.setFacetMinCount(1); // 設置facet最少的統計數量
        query.setFacetLimit(10); // facet結果的返回行數
        query.addFacetField("categoryId", "regionId"); // facet的字段
        query.setFacetSort(FacetParams.FACET_SORT_COUNT);
        query.addSort(new SortClause("id", ORDER.asc)); // 排序
        QueryResponse response = core.query(query);
        List<Item> items_rep = response.getBeans(Item.class);
        List<FacetField> facetFields = response.getFacetFields();
        // 因爲上面的start和rows均設置爲0,所以這裏不會有query結果輸出
        System.out.println("--------------------");
        System.out.println("Search result:");
        for (Item item : items_rep) {
            System.out.println("id=" + item.getId() + "\tsubject=" + item.getSubject()
                    + "\tregion=" + mapRegion.get(item.getRegionId())
                    + "\tcategory=" + mapCategory.get(item.getCategoryId())
                    + "\tprice=" + item.getPrice());
        }
        // 打印所有facet
        for (FacetField ff : facetFields) {
            System.out.println("--------------------");
            System.out.println("name=" + ff.getName() + "\tcount=" + ff.getValueCount());
            System.out.println("--------------------");
            switch (ff.getName()) {
            case "regionId":
                printOut(mapRegion, ff.getValues());
                break;
            case "categoryId":
                printOut(mapCategory, ff.getValues());
                break;
            }
        }
    }
    
    @SuppressWarnings({ "rawtypes" })
    private static void printOut(HashMap map, List<Count> counts) {
        for (Count count : counts) {
            System.out.println("name=" + map.get(Integer.parseInt(count.getName())) + "\tcount=" + count.getCount());
        }
        System.out.println("--------------------");
    }

    private static Item makeItem(long id, String subject, String content, int regionId, int categoryId, float price) {
        Item item = new Item();
        item.setId(id);
        item.setSubject(subject);
        item.setContent(content);
        item.setRegionId(regionId);
        item.setCategoryId(categoryId);
        item.setPrice(price);
        return item;
    }
}
複製代碼

運行結果:

 


 

 

如果把測試例子中的這句query:

query.setQuery("*:*");

修改爲:

query.setQuery("subject:*出租* && price:[1000 TO 8000]");

運行結果將爲:

 

如果將:

query.setFacetMinCount(1); // 設置facet最少的統計數量

修改爲:

query.setFacetMinCount(0); // 設置facet最少的統計數量

運行結果爲:

比較上面兩個運行結果圖可以看出,這個setFacetMinCount(...)方法是過濾將最少統計量的數據


 

當然,也可以使用solr admin的瀏覽器地址欄進行訪問查詢:

http://localhost:8899/solr/mycore/select?q=subject:*出租* AND price :[1000 TO 8000]&wt=json&indent=true&facet=true&facet.field=categoryId&facet.field=regionId&facet.sort=count

運行輸出:

 

發佈了74 篇原創文章 · 獲贊 8 · 訪問量 30萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章