1. 程式人生 > >solr進階四:建立檔案索引

solr進階四:建立檔案索引

索引資料來源並不會一定來自於資料庫、XMLJSONCSV這類結構化資料,很多時候也來自於PDFwordhtmlwordMP3等這類非結構化資料,從這類非結構化資料建立索引,solr也給我們提供了很好的支援,利用的是apache tika

下面我們來看看在solr4.10中如何從pdf檔案建立索引。

先配置檔案索引

新建core,儲存檔案型索引,具體步驟參考:

匯入jar

在工作目錄下新建一個extract資料夾,用來存放solr擴充套件的jar包。

\solr_tomcat\solr\pdf_core\extract

拷貝\solr-4.10.2\dist下的solr-cell-4.10.2.jar

extract資料夾中,接著把

\solr-4.10.2\contrib\extraction\lib下的索引jar包拷貝到extract資料夾中。

配置solrconfig.xml

新增請求解析配置:

<requestHandler name="/extract" class="solr.extraction.ExtractingRequestHandler" >  
       <lst name="defaults">  
        <str name="fmap.content">text</str>  
        <str name="lowernames">true</str>  
        <str name="uprefix">attr_</str>  
        <str name="captureAttr">true</str>  
       </lst>  
</requestHandler>

指定依賴包位置:

<span style="font-size:18px;"><lib dir="extract" regex=".*\.jar" /></span>

注意,這個相對位置不是相對於配置檔案所在資料夾位置,而是相對core主目錄的。比如我的配置檔案在\solr_tomcat\solr\pdf_core\conf, 但是我的jar包在\solr_tomcat\solr\pdf_core\extract那麼我的相對路徑就是extract而不是../extract

配置schema.xml,配置索引欄位的型別,也就是field型別。

其中text_general

型別我們用到2txt檔案(stopwords.txtsynonyms.txt),這2txt檔案在釋出包示例core裡面有位置在:\solr_tomcat\solr\collection1\conf,複製這2txt檔案到新建的core下面的conf目錄下,和schema.xml一個位置。

注意:如果是複製貼上core來新建core的話,原來的配置檔案有些field是已經定義的,要注意把重複定義的去掉一個!

<fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>  
  <fieldtype name="string"  class="solr.StrField" sortMissingLast="true" omitNorms="true"/>  
  <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" />  
       <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>

配置索引欄位,也就是field

其中有個動態型別欄位,attr_*,這個是什麼意思呢。也就是solr在解析檔案的時候,檔案本身有很多屬性,具體有哪些屬性是不確定的,solr全部把他解析出來以attr作為字首加上檔案本身的屬性名,組合在一起就成了field的名稱

<field name="id"        type="string"       indexed="true"  stored="true"  multiValued="false" required="true"/>  
 <field name="text"      type="text_general" indexed="true"  stored="true"/>  
 <field name="_version_" type="long"         indexed="true"  stored="true"/>  
   
 <dynamicField name="attr_*" type="text_general" indexed="true" stored="true" multiValued="true"/>

到這裡solr服務端的配置以及完成了。

測試類CreateIndexFromPDF.java

Solrj4.10裡面ContentStreamUpdateRequestaddFile方法多了一個contentType引數,指明內容型別。ContentType請參看:ContentType

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest;
import org.apache.solr.client.solrj.response.QueryResponse;

import java.io.File;
import java.io.IOException;
/**
 * Created by Lhx on 14-12-4.
 */
public class CreateIndexFromPDF {

    public static void indexFilesSolr(String fileName, String solrId) throws IOException, SolrServerException {
        String urlString = "http://localhost:8080/solr/pdf_core";
        SolrServer solr = new HttpSolrServer(urlString);
        ContentStreamUpdateRequest up = new ContentStreamUpdateRequest("/extract");
        String contentType = "application/pdf";
        up.addFile(new File(fileName), contentType);
        up.setParam("literal.id", solrId);
        up.setParam("uprefix","attr_");
        up.setParam("fmap.content","attr_content");
        up.setAction(AbstractUpdateRequest.ACTION.COMMIT, true, true);

        solr.request(up);

        QueryResponse rsp = solr.query(new SolrQuery("*:*"));
        System.out.println(rsp);
    }

    public static void main(String[] args) {
        String fileName = "F:\\Sencha_Touch_2.0使用者指南(中文版).pdf";
        String solrId = "Sencha_Touch_2.0使用者指南(中文版).pdf";
        try {
            indexFilesSolr(fileName,solrId);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (SolrServerException e) {
            e.printStackTrace();
        }
    }
}

執行上面程式碼,便把我們的pdf檔案上傳到solr伺服器,解析、建立索引

後面的solr.query是執行一個查詢,查詢解析索引後結果。解析後pdf就變成了純文字的內容,在控制檯可以看到很多文件其他資訊。

Solr解析完pdf、建立索引後,我們也可以在solr的管理介面檢視索引結果。如下圖。

選擇“Query”,直接點選“Execute Query”按鈕就可以了:

後記:

重啟tomcat後報重複定義欄位的錯誤,這個在前面的實踐中就有這個錯誤,所以很快就在schema.xml中找到重複定義的idlong等型別欄位,刪掉就可以了。

接著啟動tomcat,還是報出無法載入某某jar包的提示錯誤,後來才發現

<lib dir="extract" regex=".*\.jar" />

這個dir指定的目錄地址寫錯了,導致tomcat報錯。

啟動tomcat後再也沒有報錯,在java控制檯執行程式碼,報出以下錯誤:

原來是我把urlString地址寫錯了,寫成了:

http://localhost:8080/solr

沒有指定究竟上傳到哪個指定的core裡面,修改後就能提交PDF文件資訊了。

附錄:

solrconfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!--
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements.  See the NOTICE file distributed with
 this work for additional information regarding copyright ownership.
 The ASF licenses this file to You under the Apache License, Version 2.0
 (the "License"); you may not use this file except in compliance with
 the License.  You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-->

<!--
 This is a stripped down config file used for a simple example...  
 It is *not* a good example to work from. 
-->
<config>
    <luceneMatchVersion>4.10.2</luceneMatchVersion>
    <!--  The DirectoryFactory to use for indexes.
          solr.StandardDirectoryFactory, the default, is filesystem based.
          solr.RAMDirectoryFactory is memory based, not persistent, and doesn't work with replication. -->
    <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.StandardDirectoryFactory}"/>

    <dataDir>${solr.core0.data.dir:}</dataDir>

    <!-- To enable dynamic schema REST APIs, use the following for <schemaFactory>:
    
         <schemaFactory class="ManagedIndexSchemaFactory">
           <bool name="mutable">true</bool>
           <str name="managedSchemaResourceName">managed-schema</str>
         </schemaFactory>
         
         When ManagedIndexSchemaFactory is specified, Solr will load the schema from
         he resource named in 'managedSchemaResourceName', rather than from schema.xml.
         Note that the managed schema resource CANNOT be named schema.xml.  If the managed
         schema does not exist, Solr will create it after reading schema.xml, then rename
         'schema.xml' to 'schema.xml.bak'. 
         
         Do NOT hand edit the managed schema - external modifications will be ignored and
         overwritten as a result of schema modification REST API calls.
  
         When ManagedIndexSchemaFactory is specified with mutable = true, schema
         modification REST API calls will be allowed; otherwise, error responses will be
         sent back for these requests. 
    -->
    <schemaFactory class="ClassicIndexSchemaFactory"/>

    <updateHandler class="solr.DirectUpdateHandler2">
        <updateLog>
            <str name="dir">${solr.core0.data.dir:}</str>
        </updateLog>
    </updateHandler>

    <!-- realtime get handler, guaranteed to return the latest stored fields 
      of any document, without the need to commit or open a new searcher. The current 
      implementation relies on the updateLog feature being enabled. -->
    <requestHandler name="/get" class="solr.RealTimeGetHandler">
        <lst name="defaults">
            <str name="omitHeader">true</str>
        </lst>
    </requestHandler>

    <requestHandler name="/replication" class="solr.ReplicationHandler" startup="lazy"/>

    <requestDispatcher handleSelect="true">
        <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="2048" formdataUploadLimitInKB="2048"/>
    </requestDispatcher>

    <requestHandler name="standard" class="solr.StandardRequestHandler" default="true"/>
    <requestHandler name="/analysis/field" startup="lazy" class="solr.FieldAnalysisRequestHandler"/>
    <requestHandler name="/update" class="solr.UpdateRequestHandler"/>
    <requestHandler name="/admin/" class="org.apache.solr.handler.admin.AdminHandlers"/>

    <requestHandler name="/admin/ping" class="solr.PingRequestHandler">
        <lst name="invariants">
            <str name="q">solrpingquery</str>
        </lst>
        <lst name="defaults">
            <str name="echoParams">all</str>
        </lst>
    </requestHandler>

    <!--新新增的內容-->
    <requestHandler name="/extract" class="solr.extraction.ExtractingRequestHandler">
        <lst name="defaults">
            <str name="fmap.content">text</str>
            <str name="lowernames">true</str>
            <str name="uprefix">attr_</str>
            <str name="captureAttr">true</str>
        </lst>
    </requestHandler>

    <lib dir="extract" regex=".*\.jar"/>


    <!-- config for the admin interface -->
    <admin>
        <defaultQuery>solr</defaultQuery>
    </admin>

</config>

schema.xml

<?xml version="1.0" ?>
<!--
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements.  See the NOTICE file distributed with
 this work for additional information regarding copyright ownership.
 The ASF licenses this file to You under the Apache License, Version 2.0
 (the "License"); you may not use this file except in compliance with
 the License.  You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-->

<schema name="example core zero" version="1.1">

    <!-- general -->

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

    <!-- 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>name</defaultSearchField>

    <!-- SolrQueryParser configuration: defaultOperator="AND|OR" -->
    <solrQueryParser defaultOperator="OR"/>

    <!--新新增的,其中long、String等欄位原來配置檔案就有,注意刪除-->
    <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
    <fieldtype name="string" class="solr.StrField" sortMissingLast="true" omitNorms="true"/>
    <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"/>
            <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>

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

    <dynamicField name="attr_*" type="text_general" indexed="true" stored="true" multiValued="true"/>

</schema>

參考文章:


相關推薦

solr建立檔案索引

索引資料來源並不會一定來自於資料庫、XML、JSON、CSV這類結構化資料,很多時候也來自於PDF、word、html、word、MP3等這類非結構化資料,從這類非結構化資料建立索引,solr也給我們提供了很好的支援,利用的是apache tika。 下面我們來看看在sol

AndroidDatabinding的使用(基礎篇)

  Data Binding是2015年Google I/O大會上提出的,從Beta版至今,Data Binding已經是一個可用度較高,也能帶來實際生產力提升的技術。 Data Binding顧名思義就是資料繫結,是Google對MVVM在Android上的

solrsolr對數字和單個字元的搜尋

solr中配有分詞器,但分詞器裡面有大寫轉換為小寫的過濾器時,數字就會被過濾。比如123中國ABC。123就會被過濾掉了,所以才查1|12|123都會失敗。 根據賬號來搜尋,當賬號在資料庫中是整型

分針網——每日分享JavaScript()js字符串轉換成數字的三種方法

加入職業技能圈 q群:272292492 更多文章:www.f-z.cn 在js讀取文本框或者其它表單數據的時候獲得的值是字符串類型的,例如兩個文本框a和b,如果獲得a的value值為11,b的value值為9 ,那麽a.valu

Java(十二)Java中多執行緒使用匿名內部類的方式進行建立3種方式

Java中多執行緒使用匿名內部類的方式進行建立3種方式 package cn.edu.ujn.demo; // 匿名內部類的格式: public class ThreadDemo {

android4step1android小知識 檔案儲存

檔案儲存 作為一個開發者,我們經常需要通過快取一些檔案到 SD 卡中,常見的方式就是,通過: File sdCard = Environment.getExternalStorageDirectory(); 獲取 SD 卡根目錄,然後自定義檔案/檔名進行檔案儲存.這樣做法的結果就是,當手

服務端技術()一篇文讀懂分散式系統本質高吞吐、高可用、可擴充套件

服務端技術進階( 四)一篇文讀懂分散式系統本質:高吞吐、高可用、可擴充套件 承載量是分散式系統存在的原因   當一個網際網路業務獲得大眾歡迎的時候,最顯著碰到的技術問題,就是伺服器非常繁忙。當每天有1000萬個使用者訪問你的網站時,無論你使用什麼樣的伺服

websphere服務建立概要檔案、刪除概要檔案

cd /usr/IBM/WebSphere/AppServer/bin 檢視刪除概要 ./manageprofiles.sh -listProfiles [Dmgr01, AppSrv01] ./manageprofiles.sh -delete -profileNam

教程用Python建立全新二層神經結構

全文共5234字,預計學習時長10分鐘 圖片來源:unsplash.com/@alinnnaaaa 本文將介紹如何建立進階

建立高級web測試計劃

cookie 手動 建立 fine support 技術分享 瀏覽器 fix agent 發送帶有Header的請求 參考:http://jmeter.apache.org/usermanual/build-adv-web-test-plan.html#header_m

HTML5 系列indexedDB 數據庫

連接數據庫 function request html5 客戶端 前言在 HTML5 的本地存儲中,有一種叫 indexedDB 的數據庫,該數據庫是一種存儲在客戶端本地的 NoSQL 數據庫,它可以存儲大量的數據。從上篇:HTML5 進階系列:web Storage ,我們知道

Python學習之旅—面向對象知識類的命名空間,類的組合與繼承

ati error role ont 之前 obj say 報錯 抽象 前言   上篇博客筆者帶領大家初步梳理了Python面向對象的基礎知識,本篇博客將專註於解決三個知識點:類的命名空間,類的組合以及面向對象的三大特性之一繼承,一起跟隨筆者老看看今天的內容吧。 1.

Android筆記AIDL內部實現詳解 (二)

ucc == 筆記 null stack 直接 android 最好 public 接著上一篇分析的aidl的流程解析。知道了aidl主要就是利用Ibinder來實現跨進程通信的。既然是通過對Binder各種方法的封裝,那也可以不使用aidl自己通過Binder來實現跨進

java 代理和動態代理

實現 public rgs tostring 開源項目 body llb ack code 靜態代理:   定義頂級接口:Iservice //目標類和代理類都實現該接口 public interface Iservice { public String serv

用裝飾器做一個登陸功能(

read AD OS pos 商城 *args readline wrapper 改變 1 dic = { 2 ‘username‘:None, 3 ‘status‘:False 4 } 5 def login(flag): # 傳入

面向對象6元類

ise and 否則 tag weak wal 方法 pan strong 六 練習題 練習一:在元類中控制把自定義類的數據屬性都變成大寫 class Mymetaclass(type): def __new__(cls,name,bases,attrs):

Python爬蟲新手怎樣讀取非結構化、圖像、視頻、語音數據

image clas 訓練 在線的 功能 方式 base64編碼 contain width 通過open讀取之後會返回一個圖像文件對象,後續所有的圖像處理都基於該對象進行。上述代碼執行後,通過 img.show() 會調用系統默認的圖像瀏覽器查看打

T-SQL查詢--理解SQL Server中索引的概念,原理以及其他

工具 def microsoft 需要 blog b- eve 實現 中一 簡介 在SQL Server中,索引是一種增強式的存在,這意味著,即使沒有索引,SQL Server仍然可以實現應有的功能。但索引可以在大多數情況下大大提升查詢性能,在OLAP

3.2.4)鈑金件-材料選擇

沒有 3.5 3.1 進階 暴露 font 加工 生產線 速度 3.常用鈑金材料介紹 適合於沖壓加工的鈑金材料非常多,本書介紹廣泛應用於電子電器行業的鈑金材料。 3.1 普通冷軋板SPCC SPCC是指鋼錠經過冷軋機連續軋制成要求厚度的鋼板卷料或片料。SPCC表面沒有

Xadmin如何增加一列

init 9.png pla plugin cto object 實現 list 下標 主要實現參考 relate.py插件,通過繼承BaseAdminPlugin實現,實現效果: 主要的的代碼如下: from xadmin.views import BaseAdminP