Solr 入門

solr 介紹

什麼是 solr

Solr是apache的頂級開源項目,它是使用java開發 ,基於lucene的全文檢索服務器。php

Solr比lucene提供了更多的查詢語句,並且它可擴展、可配置,同時它對lucene的性能進行了優化。java

Solr是如何實現全文檢索的呢?mysql

索引流程:solr客戶端(瀏覽器、java程序)能夠向solr服務端發送POST請求,請求內容是包含Field等信息的一個xml文檔,經過該文檔,solr實現對索引的維護(增刪改)web

搜索流程:solr客戶端(瀏覽器、java程序)能夠向solr服務端發送GET請求,solr服務器返回一個xml文檔。sql

Solr一樣沒有視圖渲染的功能。數據庫

solr 和 lucene 的區別

Lucene 是一個全文檢索引擎工具包,它是一個 jar 包,不能獨立運行,對外提供服務。apache

Solr 是一個全文檢索服務器,它能夠單獨運行在 servlet 容器,能夠單獨對外提供搜索和索引功能。Solr 比 lucene 在開發全文檢索功能時,更快捷、更方便。 json

solr 的安裝配置

下載

solr 和 lucene 的版本時同步更新的,最新版本是5.2.1數組

下載地址:http://archive.apache.org/dist/lucene/solr/瀏覽器

環境

jdk:1.7及以上 solr:4.10.3 mysql:5x web服務器:tomcat7

初始化數據庫腳本

solr 安裝配置

  • 安裝 tomcat
  • 將solr-4.10.3\example\webapps 目錄下 solr.war 拷貝到 tomcat webapps 目錄下
  • 解壓縮 war 包,解壓縮以後,將 war 包刪掉
  • 添加 solr 擴展服務包。將 solr-4.10.3\example\lib\ext 目錄下 jar 拷貝到 tomcat solr WEB-INF lib 目錄下
  • 添加 log4j.properties。拷貝 solr-4.10.3\example\resources 目錄下 log4j.properties 到 apache-tomcat-7.0.57\webapps\solr\WEB-INF\classes ,目錄不存在沒有則建立。
  • 在 web.xml 中指定 solrhome 的目錄

solrcore 安裝

solrcore 和 solrhome

Solrhome是solr服務運行的主目錄,一個solrhome目錄裏面包含多個solrcore目錄,一個solrcore目錄裏面了一個solr實例運行時所須要的配置文件和數據文件。

每個solrcore均可以單獨對外提供搜索和索引服務。 多個solrcore之間沒有關係。

solrcore 和 solrhome 的目錄結構

solrhome: solr-4.10.3\example\solr solrcore: solr-4.10.3\example\solr\collection1 包含配置文件,索引文件日誌信息

solrcore 的安裝

安裝 solrcore 須要先安裝 solrhome 將上面solrhome下的文件拷貝到web.xml中指定的solrhome中便可

solrcore 的配置

配置 solrcore 的 conf 目錄下的 solrconfig.xml 配置文件,來配置 solrcore 的運行信息。

在該文件中,主要配置三個標籤:lib 標籤、datadir標籤、requestHandler 標籤。

lib 標籤

solrcore 須要添加一個擴展依賴包,經過 lib 標籤來指定依賴包的地址

solr.install.dir 表示 solrcore 的安裝目錄

拷貝 example 目錄下的 contrib 和 dis 目錄到

修改 lib 標籤

datadir 標籤

每一個 solrcore 都有本身的索引文件目錄,默認在 solrcore 目錄下的 data 中。

data數據目錄下包括了index索引目錄 和tlog日誌文件目錄。 若是不想使用默認的目錄也能夠經過solrConfig.xml更改索引目錄 ,以下:

requestHandler 標籤

requestHandler 請求處理器,定義索引和搜索的訪問方式。 經過 /update 維護索引,能夠完成對索引的添加、修改、刪除操做。

提交 xml、json 數據完成索引維護。

經過 /select 搜索索引

設置搜索參數完成搜索,搜索參數也能夠設置一些默認值,以下:

<requestHandler name="/select" class="solr.SearchHandler">
    <!-- 設置默認的參數值,能夠在請求地址中修改這些參數-->
    <lst name="defaults">
        <str name="echoParams">explicit</str>
        <int name="rows">10</int><!--顯示數量-->
        <str name="wt">json</str><!--顯示格式-->
        <str name="df">text</str><!--默認搜索字段-->
    </lst>
</requestHandler>
複製代碼

solr 界面

Dashboard

儀表盤,顯示 solr 實例運行時間、版本、系統資源、jvm等信息。 、

Logging

solr 運行日誌信息

Cloud

Cloud即SolrCloud,即Solr雲(集羣),當使用Solr Cloud模式運行時會顯示此菜單.

Core Admin

solrcore 的管理界面,這裏能夠添加 solrcore 實例。

java properties

solr 在 jvm 運行環境中的屬性信息。

Thread Dump

顯示 solr server 中當前活躍線程信息,同時也能夠跟蹤線程運行棧信息。

Core selector

選擇一個 solrcore 進行詳細操做,以下:

Analysis

經過此界面能夠測試索引分析器和搜索分析器的執行狀況。 注:solr 中,分析器是綁定在域類型中的。

dataimport

能夠定義數據導入處理器,從關係數據庫導入到 solr 索引庫中。默認配置,須要手工配置。

Document

經過 /update 表示更新索引,solr 默認根據 id(惟一約束) 域來更新 document 的內容,若是根據 id 值搜索不到 id 域則會執行添加操做,若是找到則更新。

經過此菜單能夠建立索引、更新索引、刪除索引等操做,界面以下:

  • overwrite="true" : solr在作索引的時候,若是文檔已經存在,就用xml中的文檔進行替換
  • commitWithin="1000" : solr 在作索引的時候,每一個1000(1秒)毫秒,作一次文檔提交。爲了方便測試也能夠在Document中當即提交,後添加「」

Query

經過/select執行搜索索引,必須指定「q」查詢條件方可搜索。

多 solrcore 配置

配置多solrcore的好處: 一、在進行 solrcloud 的時候,必須配置多solrcore 二、每一個 solrcore 之間是獨立的,均可以單獨對外提供服務。不一樣的業務模塊能夠使用不一樣的solrcore 來提供搜索和索引服務。

添加

  • 第一步:複製 solrhome 下的 collection1 目錄到本目錄下,修更名稱爲 collection2
  • 修改 solrcore 目錄下的 core.properties
    這樣多 solrcore 就配置完成了。

Solr 基本使用

schema.xml

在 schema.xml 文件中,主要配置了 solrcore 的一些數據信息,包括 Field 和 FieldType 的定義等信息,在 solr 中,Field 和 FieldType 都須要先定義後使用。

Field

定義Field域

Name:指定域的名稱 Type:指定域的類型 Indexed:是否索引 Stored:是否存儲 Required:是否必須 multiValued:是否多值,好比商品信息中,一個商品有多張圖片,一個Field像存儲多個值的話,必須將multiValued設置爲true。

dynamicField

動態域

Name:指定動態域的命名規則

uniqueKey

指定惟一鍵

id

其中的id是在Field標籤中已經定義好的域名,並且該域要設置爲required爲true。

一個schema.xml文件中必須有且僅有一個惟一鍵

copyField

複製域

Source:要複製的源域的域名 Dest:目標域的域名

由dest指的的目標域,必須設置multiValued爲true。

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:指定過濾器

中文分詞器

使用ikanalyzer進行中文分詞

  • 第一步:將ikanalyzer的jar包拷貝到如下目錄

  • 第二步:將ikanalyzer的擴展詞庫的配置文件拷貝到 目錄

  • 配置 FieldType

  • 配置使用中文分詞的 field

  • 重啓 tomcat

配置業務 Field

需求

對京東案例中的 products 表的數據進行索引,因此須要定義對應的 field 域。

分析配置

須要往索引庫添加的字段有: pid、name、catalog、catalog_name、price、description、picture

FieldType: 經分析,因爲中文分詞器已經配置完FieldType,因此目前FieldType已經知足須要,無需配置。

Field: Pid: 因爲pid在products表中是惟一鍵,並且在solr的shema.xml中已有一個id的惟一鍵配置,因此不須要再從新定義pid域。

Name:

<!-- 商品名稱 -->
<field name="product_name" type="text_ik" indexed="true" stored="true"/>
複製代碼

Catalog、catalog_name:

<!-- 商品分類ID -->
<field name="product_catalog" type="string" indexed="true" stored="true"/> 
<!-- 商品分類名稱 -->
<field name="product_catalog_name" type="string" indexed="true" stored="false"/>
複製代碼

Price:

<!-- 商品價格 -->
<field name="product_price" type="float" indexed="true" stored="true"/>
複製代碼

Description:

<!-- 商品描述 -->
<field name="product_description" type="text_ik" indexed="true" stored="false"/>
複製代碼

Picture:

<!-- 商品圖片地址 -->
<field name="product_picture" type="string" indexed="false" stored="true"/> 
複製代碼
<!-- 目標域 -->
<field name="product_keywords" type="text_ik" indexed="true" stored="true" multiValued="true"/>

<!-- 將商品名稱添加到目標域 -->
<copyField source="product_name" dest="product_keywords"/>

<!-- 將商品描述添加到目標域 -->
<copyField source="product_description" dest="product_keywords"/>
複製代碼

Dataimport

該插件能夠將數據庫中指定的sql語句的結果導入到solr索引庫中。

  • 第一步:添加 jar 包 Dataimport的jar包(solr-4.10.3\dist\solr-dataimporthandler-extras-4.10.3.jar) 複製到

    修改 solrconfig.xml 文件,添加 lib 標籤 <lib dir="${solr.install.dir:../..}/contrib/dataimporthandler/lib" regex=".*\.jar" />

    mysql 數據庫驅動包 複製 mysql 驅動包到:

    修改solrconfig.xml文件,添加lib標籤 <lib dir="${solr.install.dir:../..}/contrib/db/lib" regex=".*\.jar" />

  • 第二步:配置 requesthandler 在 solrconfig.xml 中,添加一個 dataimport 的 requestHandler

    <requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
          <lst name="defaults">
              <str name="config">data-config.xml</str>
          </lst>
    </requestHandler>
    複製代碼
- 第三步:建立 data-config.xml
  在 solrconfig.xml 同級目錄下,建立 data-config.xml
![](http://pbzzkhjh1.bkt.clouddn.com/1c648865-30cb-4dbe-9133-525692211bf4.jpg)
```xml
<dataConfig>
    <dataSource 
        type="JdbcDataSource"
        driver="com.mysql.jdbc.Driver"
        url="jdbc:mysql://localhost:3306/taotao" 
        user="root"
        password="root"/>

    <document>
        <entity name="products" query="select pid,name,catalog,catalog_name,price,description,picture from products ">
            <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>
複製代碼
  • 第四步:重啓 tomcat

solrj 的使用

什麼是 solrj

solrj 就是 solr 服務器的 java 客戶端

環境準備

jdk ide tomcat solrj

搭建工程

  • solrj 的依賴包和核心包

  • solrj 的擴展服務包

使用 solrj 完成索引維護

添加/修改索引

在solr中,索引庫中都會存在一個惟一鍵,若是一個Document的id存在,則執行修改操做,若是不存在,則執行添加操做。

@Test
    public void insertAndUpdateIndex() throws Exception {
        // 建立HttpSolrServer
        HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr");
        // 建立Document對象
        SolrInputDocument doc = new SolrInputDocument();
        doc.addField("id", "c001");
        doc.addField("name", "solr test111");
        // 將Document對象添加到索引庫
        server.add(doc);
        // 提交
        server.commit();
    }
複製代碼

刪除索引

根據指定 id 來刪除
根據條件來刪除
@Test
    public void deleteIndex() throws Exception {
        // 建立HttpSolrServer
        HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr");

        // 根據指定的ID刪除索引
        // server.deleteById("c001");

        // 根據條件刪除
        server.deleteByQuery("id:c001");

        // 刪除所有(慎用)
        server.deleteByQuery("*:*");

        // 提交
        server.commit();
    }
複製代碼

查詢索引

簡單查詢
@Test
    public void search01() throws Exception {
        // 建立HttpSolrServer
        HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr");
        // 建立SolrQuery對象
        SolrQuery query = new SolrQuery();
        // 輸入查詢條件
        query.setQuery("product_name:小黃人");
        // 執行查詢並返回結果
        QueryResponse response = server.query(query);
        // 獲取匹配的全部結果
        SolrDocumentList list = response.getResults();
        // 匹配結果總數
        long count = list.getNumFound();
        System.out.println("匹配結果總數:" + count);
        for (SolrDocument doc : list) {
            System.out.println(doc.get("id"));
            System.out.println(doc.get("product_name"));
            System.out.println(doc.get("product_catalog"));
            System.out.println(doc.get("product_price"));
            System.out.println(doc.get("product_picture"));
            System.out.println("=====================");
        }
    }
複製代碼
複雜查詢

solr的查詢語法

1.q - 查詢關鍵字,必須的,若是查詢全部使用*:*。 請求的q是字符串

2.fq - (filter query)過慮查詢,做用:在q查詢符合結果中同時是fq查詢符合的,例如:: 請求fq是一個數組(多個值)

過濾查詢價格從1到20的記錄。 也能夠在「q」查詢條件中使用product_price:[1 TO 20],以下:
也能夠使用「*」表示無限,例如: 20以上:product_price:[20 TO ] 20如下:product_price:[ TO 20]

3.sort - 排序,格式:sort=+<desc|asc>[,+<desc|asc>]… 。示例:

按價格降序

4.start - 分頁顯示使用,開始記錄下標,從0開始

5.rows - 指定返回結果最多有多少條記錄,配合start來實現分頁。 實際開發時,知道當前頁碼和每頁顯示的個數最後求出開始下標。

6.fl - 指定返回那些字段內容,用逗號或空格分隔多個。

顯示商品圖片、商品名稱、商品價格

7.df-指定一個搜索Field

也能夠在SolrCore目錄 中conf/solrconfig.xml文件中指定默認搜索Field,指定後就能夠直接在「q」查詢條件中輸入關鍵字。

8.wt - (writer type)指定輸出格式,能夠有 xml, json, php, phps, 後面 solr 1.3增長的,要用通知咱們,由於默認沒有打開。

9.hl 是否高亮 ,設置高亮Field,設置格式前綴和後綴。

代碼

@Test
    public void search02() throws Exception {
        // 建立HttpSolrServer
        HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr");
        // 建立SolrQuery對象
        SolrQuery query = new SolrQuery();

        // 輸入查詢條件
        query.setQuery("product_name:小黃人");
        // query.set("q", "product_name:小黃人");

        // 設置過濾條件
        // 若是設置多個過濾條件的話,須要使用query.addFilterQuery(fq)
        query.setFilterQueries("product_price:[1 TO 10]");

        // 設置排序
        query.setSort("product_price", ORDER.asc);
        // 設置分頁信息(使用默認的)
        query.setStart(0);
        query.setRows(10);

        // 設置顯示的Field的域集合
        query.setFields("id,product_name,product_catalog,product_price,product_picture");

        // 設置默認域
        query.set("df", "product_keywords");

        // 設置高亮信息
        query.setHighlight(true);
        query.addHighlightField("product_name");
        query.setHighlightSimplePre("<em>");
        query.setHighlightSimplePost("</em>");

        // 執行查詢並返回結果
        QueryResponse response = server.query(query);
        // 獲取匹配的全部結果
        SolrDocumentList list = response.getResults();
        // 匹配結果總數
        long count = list.getNumFound();
        System.out.println("匹配結果總數:" + count);

        // 獲取高亮顯示信息
        Map<String, Map<String, List<String>>> highlighting = response
                .getHighlighting();
        for (SolrDocument doc : list) {
            System.out.println(doc.get("id"));

            List<String> list2 = highlighting.get(doc.get("id")).get(
                    "product_name");
            if (list2 != null)
                System.out.println("高亮顯示的商品名稱:" + list2.get(0));
            else {
                System.out.println(doc.get("product_name"));
            }

            System.out.println(doc.get("product_catalog"));
            System.out.println(doc.get("product_price"));
            System.out.println(doc.get("product_picture"));
            System.out.println("=====================");
        }
    }
複製代碼
相關文章
相關標籤/搜索