solr教程


轉載請注明出處:http://www.cnblogs.com/zhuxiaojie/p/5764680.html

 

本教程基於solr5.5

 

前言

至於為什么要用solr5.5,因為最新的6.10,沒有中文的分詞器支持,這里使用的是ik分詞器,剛好支持到5.5

ik分詞器下載地址 :https://github.com/EugenePig/ik-analyzer-solr5  , 下載完之后使用maven命令, mvn package 即可生成jar文件,或者下載我編譯好的 http://pan.baidu.com/s/1o7P0846

solr5.5下載地址: http://apache.fayea.com/lucene/solr/5.5.2/

tomcat8下載,下載地址就不說了

 

 

一:安裝配置

下載完成之后,解壓solr文件,解壓tomcat

 1.1 在tomcat安裝solr,並且建立solrCore

  1. 把solr5.5目錄下的server/solr-webapp/webapp 重命名為solr,並且放置到tomcat/webapp的目錄下。 
  2. 打開tomcat/webapp/solr/WEB-INF/web.xml
  3. 新建一個文件夾,不要中文目錄,用來做solrHome,也就是solrCore的實例存放位置
  4. 在tomcat/webapp/solr/WEB-INF/web.xml中配置solr的地址
  5. 在tomcat/webapp/solr/WEB-INF/文件夾中,建立classes目錄

  6. 把solr5.5/server/resource/log4j.properties 復制到上一步建立的classes目錄中
  7. 把solr5.5/server/lib/ext/目錄下的所有jar文件復制到tomcat/webapp/solr/WEB-INF/lib/中,這是一些日志用的jar包,不然啟動報錯。
  8. 這個時候,可以輸入http://127.0.0.1:8080/solr/admin.html來訪問到solr的控制界面了。
  9. 接下來就是創建solrCore。
  10. 目前solrHome目錄是空的,我們創建一個空文件夾core1,這個就是我們的一個實例,然后把solr5.5/server/solr/configsets/sample_techproducts_configs/conf/ 這個文件復制到solrHome/core1中。
  11. 把solr5.5/server/solr/solr.xml復制到solrHome目錄下。
  12. 在solr的管理控制台界面,添加一個core1
  13.  

  14. 這下就創建成功了一個實例core1,yge 請注意我打碼的部分,需要先執行第11步操作,否則的話,會無法創建solr core,也就是會有錯誤信息,這是solr的一個bug,但是至今沒有修復。

 

1.2 安裝ik中文分詞器

  1. 准備好ik分詞器的jar包,可以自己編譯,也可以下載我生成的。然后把它復制到tomcat/webapp/solr/WEB-INF/lib里面。(千萬不要復制到tomcat/lib中,這樣會找不到lucene的類)
  2. 打開solrHome/core1/conf/managed-schema文件,在最下方,追加如下配置
  3.     <fieldType name="text_ik" class="solr.TextField">
            <analyzer type="index" useSmart="false"
                class="org.wltea.analyzer.lucene.IKAnalyzer" />
            <analyzer type="query" useSmart="true"
                class="org.wltea.analyzer.lucene.IKAnalyzer" />
        </fieldType>

     

  4. 啟動tomcat,即可看到text_ik分詞
  5.  

 

1.3 插入的文檔必須與域相匹配

域,我個人也稱它為字段,它在solr中有特定的含義,就類似數據庫中表的列一樣,規范着寫入的數據,我們先來做個例子。

可以看到,我這次插入的文檔,有id,title當然,在solr中,每一條記錄都必須有着一個唯一的id,它就類似數據庫中的主鍵,不可重復。這條記錄的插入是成功的。

但是,如果我把title改成title1,這就與定義的字段不一樣了,就會報錯,如下圖所示

可以看到,這里提示,未知的字段 title1.

 

1.4 域的定義 field

先拿出一條配置來看一下

<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" /> 

 認識一下這些屬性

  name:域名

  type:域的類型,必須匹配類型,不然會報錯

  indexed:是否要作索引

  stored:是否要存儲

  required:是否必填,一般只有id才會設置

  multiValued:是否有多個值,如果設置為多值,里面的值就采用數組的方式來存儲,比如商品圖片地址(大圖,中圖,小圖等)

 

1.5 配置動態域 dynamicField

同樣的,也先拿出一條來看看

<dynamicField name="*_i"  type="string"    indexed="true"  stored="true" multiValued="true" />

何謂動態域呢?就是這個域的名稱,是由表達式組成的,只要名稱滿足了這個 表達式,就可以用這個域

 同樣的認識一下這些屬性

  name:域的名稱,該域的名稱是通過一個表達式來指定的,只要符合這這個規則,就可以使用這個域。比如  aa_i,bb_i,13_i等等,只要滿足這個表達式皆可

  type:對應的值類型,相應的值必須滿足這個類型,不然就會報錯

  indexed:是否要索引

  stored:是否要存儲

  ...其它的屬性與普通的域一至

 

 

 

 

1.6 主鍵域 uniqueKey

給出一條配置

 <uniqueKey>id</uniqueKey>

指定一個唯一的主鍵,每一個文檔中,都應該有一個唯一的主鍵,這個值不要隨便改

 

 

 

1.7 復制域 copyField

給出一條配置

<copyField source="cat" dest="text"/>

說明一下相應的屬性

  source:源域

  dest:目標域

復制域,將源域的內容復制到目標域中

注意:目標域必須是允許多值的,如下,nultiValued必須為true,因為可能多個源域對應一個目標域,所以它需要以數組來存儲

<field name="text" type="string" indexed="true" stored="true" multiValued="true"/>

 

 

 

 

1.8 域的類型 fieldType

同樣的給出一段配置,這段稍微有點復雜

    <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
      <analyzer type="index">
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
        <!-- in this example, we will only use synonyms at query time
        <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
        -->
        <filter class="solr.LowerCaseFilterFactory"/>
      </analyzer>
      <analyzer type="query">
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
        <filter class="solr.LowerCaseFilterFactory"/>
      </analyzer>
    </fieldType>

給出相應屬性的說明

  name:域的名稱

  class:指定solr的類型

  analyzer:分詞器的配置

    type: index(索引分詞器),query(查詢分詞器)

    tokenizer:配置分詞器

    filter:過濾器

 

 

 

 

1.9 業務字段的實際配置

經過上面的學習,差不多了解了一些常用的配置,如今我們用field來配置實際的業務字段,有屬性如下

當然,中文分詞還是要用的,因為我們在前面的  1.2  章節中,已經配置了一個fieldType的中文分詞,所以我們現在一律用中文分詞的域類型

 

主鍵的id就不需要配置了,默認已經把id配置為主鍵了,默認的配置如下

<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" /> 

商品名稱(需要分詞,需要存儲)

<field name="name" type="text_ik" indexed="true" stored="true"  /> 

商品分類(不需要分詞,需要存儲)

<field name="catalog" type="int" indexed="false" stored="true"  /> 

商品分類名稱(需要分詞,需要存儲)

<field name="catalog_name" type="text_ik" indexed="true" stored="true"  /> 

商品價格(不分詞,需要存儲)

<field name="price" type="double" indexed="false" stored="true"  /> 

商品描述(需要分詞,不需要存儲)

<field name="description" type="text_ik" indexed="true" stored="false"  /> 

商品圖片(不需要分詞,需要存儲)

<field name="picture" type="string" indexed="false" stored="true"  /> 

 

復制域的應用

前面我們了解了復制域,但是卻不知道它的應用場景,現在我們結合實際情況來講一下復制域

用戶在搜索框搜索的時候,有可能輸入的是商品名稱,也有可能輸入的是商品描述,也有可能輸入的是一個商品類型,那么這些值的搜索,肯定在后台是對應一個域的,那么既然如此,我們就可以把這些域合並成一個,這樣在后台只需要單獨的對這一個域進行搜索就可以了

先定義一個目標域

<field name="keywords" type="text_ik" indexed="true" stored="false"  multiValued="true"/> 

復制域,把商品名稱,商品描述,商品類型名稱復制到上面的這個域中

<copyField source="name" dest="keywords"/>
<copyField source="catalog_name" dest="keywords"/>
<copyField source="description" dest="keywords"/>

 

 

1.10 dataimport 導入數據庫數據

solr默認是沒有開啟dataimport這個功能的,所以我們要經過一點配置來開啟它

  1. 首先找到solr5.5/dist/solr-dataimporthandler-5.5.2.jar,把這個文件復制到tomcat/webapp/solr/WEB-INF/lib/下,並且找到相應數據庫的驅動包,也同樣放到該目錄。我這里用的是mysql的驅動包。
  2. 找到solr5.5/example/example-DIH/solr/db/conf/db-data-config.xml,把其復制到solrHome/core1/conf/下,並改名為data-config.xml.
  3. 找到solrHome/core1/conf/solrconfig.xml,並打開,在里面添加一段內容,如下
  4.   <requestHandler name="/dataimport" class="solr.DataImportHandler">
          <lst name="defaults">
                <str name="config">data-config.xml</str>
          </lst>
      </requestHandler>

     

  5. 打開並編輯data-config.xml,完整的配置文件如下
  6.  <dataConfig>
        <!-- 這是mysql的配置,學會jdbc的都應該看得懂 -->
        <dataSource driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/solr/useUnicode=true&characterEncoding=utf-8" user="root" password="密碼"/>
        <document>
            <!-- name屬性,就代表着一個文檔,可以隨便命名 -->
            <!-- query是一條sql,代表在數據庫查找出來的數據 -->
            <entity name="product" query="select * from products">
                <!-- 每一個field映射着數據庫中列與文檔中的域,column是數據庫列,name是solr的域(必須是在managed-schema文件中配置過的域才行) -->
                <field column="pid" name="id"/>
                <field column="name" name="product_name"/>
                <field column="catalog" name="product_catalog"/>
                <field column="catalog_name" name="product_catalog_name"/>
                <field column="price" name="product_price"/>
                <field column="description" name="product_description"/>
                <field column="picture" name="product_picture"/>
            </entity>
        </document>
    </dataConfig>

     

  7. 重啟tomcat,然后會看到如下頁面
  8.  

  9. 點擊藍色的按鈕,則開始導入,導入過程依據數量量的大小,需要的時間也不同,可以點擊右邊的Refresh status來刷新狀態,可以查看當前導入了多少條。
  10. 導入成功如下
  11.  

 

 

 

 

二:solrj的使用

代碼地址 https://github.com/zxj19951029/useSolrj

上面一章節已經講完了solr的安裝與配置,現在說一下使用solrj來維護solr的索引及操作,solrj就是一個java的客戶端,是一個jar包的使用

首先引入MAVEN的依賴,solrj的版本號要對應solr的版本號

        <dependency>
            <groupId>org.apache.solr</groupId>
            <artifactId>solr-solrj</artifactId>
            <version>5.5.2</version>
        </dependency>

 

 

2.1 增加及修改

首先說明,在solr中,增加與修改都是一回事,當這個id不存在時,則是添加,當這個id存在時,則是修改

代碼很好理解,直接給出

 

    private String serverUrl = "http://192.168.1.4:8080/solr/core1";
    /**
     * 增加與修改<br>
     * 增加與修改其實是一回事,只要id不存在,則增加,如果id存在,則是修改
     * @throws IOException 
     * @throws SolrServerException 
     */
    @Test
    public void upadteIndex() throws SolrServerException, IOException{
        //已廢棄的方法
        //HttpSolrServer server = new HttpSolrServer("http://192.168.1.4:8080/solr/core1");
        //創建
        HttpSolrClient client = new  HttpSolrClient(serverUrl);
        SolrInputDocument doc = new SolrInputDocument();
        
        doc.addField("id", "zxj1");
        doc.addField("product_name", "javaWEB技術");
        doc.addField("product_catalog", "1");
        doc.addField("product_catalog_name", "書籍");
        doc.addField("product_price", "11");
        doc.addField("product_description", "這是一本好書");
        doc.addField("product_picture", "圖片地址");
        
        client.add(doc);
        client.commit();
        
        client.close();
    }

 

 

 

2.2 刪除索引

刪除的代碼也直接給出,看代碼里面的注釋就可以了

    /**
     * 刪除索引
     * @throws Exception
     */
    @Test
    public void deleteIndex()throws Exception{
        HttpSolrClient client = new  HttpSolrClient(serverUrl);
        
        //1.刪除一個
        client.deleteById("zxj1");
        
        //2.刪除多個
        List<String> ids = new ArrayList<>();
        ids.add("1");
        ids.add("2");
        client.deleteById(ids);
        
        //3.根據查詢條件刪除數據,這里的條件只能有一個,不能以逗號相隔
        client.deleteByQuery("id:zxj1");
        
        //4.刪除全部,刪除不可恢復
        client.deleteByQuery("*:*");
        
        //一定要記得提交,否則不起作用
        client.commit();
        client.close();
    }

 

 

 

2.3 查詢

查詢稍微復雜一點,但是與solr管理界面的條件一致

這里先給出一些查詢的說明,建議查看這篇文章,個人感覺還是不錯的http://blog.csdn.net/gufengshanyin/article/details/21098879

  • q - 查詢字符串,如果查詢所有*:* (id:1)
  • fq - (filter query)過慮查詢,過濾條件,基於查詢出來的結果
  • fl - 指定返回那些字段內容,用逗號或空格分隔多個。
  • start - 分頁開始
  • rows - 分頁查詢數據
  • sort - 排序,格式:sort=<field name>+<desc|asc>[,<field name>+<desc|asc>]… 。示例:(score desc, price asc)表示先 “score” 降序, 再 “price” 升序,默認是相關性降序。
  • wt - (writer type)指定輸出格式,可以有 xml, json, php, phps。
  • fl表示索引顯示那些field( *表示所有field,如果想查詢指定字段用逗號或空格隔開(如:Name,SKU,ShortDescription或Name SKU ShortDescription【注:字段是嚴格區分大小寫的】))
  • q.op 表示q 中 查詢語句的 各條件的邏輯操作 AND(與) OR(或)
  • hl 是否高亮 ,如hl=true
  • hl.fl 高亮field ,hl.fl=Name,SKU
  • hl.snippets :默認是1,這里設置為3個片段
  • hl.simple.pre 高亮前面的格式
  • hl.simple.post 高亮后面的格式
  • facet 是否啟動統計
  • facet.field 統計field

1. “:” 指定字段查指定值,如返回所有值*:*
2. “?” 表示單個任意字符的通配
3. “*” 表示多個任意字符的通配(不能在檢索的項開始使用*或者?符號)
4. “~” 表示模糊檢索,如檢索拼寫類似於”roam”的項這樣寫:roam~將找到形如foam和roams的單詞;roam~0.8,檢索返回相似度在0.8以上的記錄。
5. 鄰近檢索,如檢索相隔10個單詞的”apache”和”jakarta”,”jakarta apache”~10
6. “^” 控制相關度檢索,如檢索jakarta apache,同時希望去讓”jakarta”的相關度更加好,那么在其后加上”^”符號和增量值,即jakarta^4 apache
7. 布爾操作符AND、||
8. 布爾操作符OR、&&
9. 布爾操作符NOT、!、- (排除操作符不能單獨與項使用構成查詢)
10. “+” 存在操作符,要求符號”+”后的項必須在文檔相應的域中存在
11. ( ) 用於構成子查詢
12. [] 包含范圍檢索,如檢索某時間段記錄,包含頭尾,date:[200707 TO 200710]

 

給出基本的代碼看一下,僅僅作為一個基本的查詢,高級的查詢,各位要自己結合文檔

package zxj.solrj;

import java.util.List;
import java.util.Map;

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.junit.Test;

/**
 * 搜索
 * @author Administrator
 *
 */
public class IndexSearch {

    private String serverUrl = "http://192.168.1.4:8080/solr/core1";
    @Test
    public void search()throws Exception{
        HttpSolrClient client = new  HttpSolrClient(serverUrl);
        
        //創建查詢對象
        SolrQuery query = new SolrQuery();
        //q 查詢字符串,如果查詢所有*:*
        query.set("q", "product_name:小黃人");
        //fq 過濾條件,過濾是基於查詢結果中的過濾
        query.set("fq", "product_catalog_name:幽默雜貨");
        //sort 排序,請注意,如果一個字段沒有被索引,那么它是無法排序的
//        query.set("sort", "product_price desc");
        //start row 分頁信息,與mysql的limit的兩個參數一致效果
        query.setStart(0);
        query.setRows(10);
        //fl 查詢哪些結果出來,不寫的話,就查詢全部,所以我這里就不寫了
//        query.set("fl", "");
        //df 默認搜索的域
        query.set("df", "product_keywords");
        
        //======高亮設置===
        //開啟高亮
        query.setHighlight(true);
        //高亮域
        query.addHighlightField("product_name");
        //前綴
        query.setHighlightSimplePre("<span style='color:red'>");
        //后綴
        query.setHighlightSimplePost("</span>");
        
        
        //執行搜索
        QueryResponse queryResponse = client.query(query);
        //搜索結果
        SolrDocumentList results = queryResponse.getResults();
        //查詢出來的數量
        long numFound = results.getNumFound();
        System.out.println("總查詢出:" + numFound + "條記錄");
        
        //遍歷搜索記錄
        //獲取高亮信息
        Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
        for (SolrDocument solrDocument : results) {
            System.out.println("商品id:" + solrDocument.get("id"));
            System.out.println("商品名稱 :" + solrDocument.get("product_name"));
            System.out.println("商品分類:" + solrDocument.get("product_catalog"));
            System.out.println("商品分類名稱:" + solrDocument.get("product_catalog_name"));
            System.out.println("商品價格:" + solrDocument.get("product_price"));
            System.out.println("商品描述:" + solrDocument.get("product_description"));
            System.out.println("商品圖片:" + solrDocument.get("product_picture"));

            //輸出高亮 
            Map<String, List<String>> map = highlighting.get(solrDocument.get("id"));
            List<String> list = map.get("product_name");
            if(list != null && list.size() > 0){
                System.out.println(list.get(0));
            }
        }
        
        client.close();
    }
}

注意:沒有索引的域,是不能用作排序的

 

 

 

 

 

三:電商平台的應用

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM