<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    lucene中文分詞組件(詞典全切分算法)下載

    下載地址:
    http://groups-beta.google.com/group/SegWord/web/IKAnalyzer.jar

    IKAnalyzer基于lucene2.0版本API開發,實現了以詞典分詞為基礎的正反向全切分算法,是Lucene Analyzer接口的實現,代碼使用例子如下:

    import org.mira.lucene.analysis.IK_CAnalyzer <------- 引用類
    import .....

    public class IKAnalyzerTest extends TestCase {

    RAMDirectory directory;
    private IndexSearcher searcher;

    public void setUp() throws Exception {

    directory = new RAMDirectory();

     

    IndexWriter writer = new IndexWriter(directory,
    new IK_CAnalyzer(), <------- 實例化類
    true);

    Document doc = new Document();
    doc.add(Field.Keyword("partnum", "Q36"));
    doc.add(Field.Text("description", "Illidium Space Modulator"));
    writer.addDocument(doc);
    writer.close();
    searcher = new IndexSearcher(directory);

    }

    public void testTermQuery() throws Exception {
    Query query = new TermQuery(new Term("partnum", "Q36"));
    Hits hits = searcher.search(query);
    assertEquals(1, hits.length());
    }
    }

    分詞效果測試,命令行如下:
    java -classpath IKAnalyzer.jar;lucene-core-2.0.0.jar org.mira.lucene.analysis.IK_CAnalyzer 中華人民共和國香港特別行政區


    該算法適合與互聯網用戶的搜索習慣和企業知識庫檢索,用戶可以用句子中涵蓋的中文詞匯搜索,如用“人民”搜索含“人民幣”的文章,這是大部分用戶的搜索思維;
    不適合用于知識挖掘和網絡爬蟲技術,全切分法容易造成知識歧義,因為在語義學上“人民”和“人民幣”是完全搭不上關系的。

    分詞效果:

    1.實現中文單詞細粒度全切分

    如:中華人民共和國
    0 - 2 = 中華
    0 - 4 = 中華人民
    0 - 7 = 中華人民共和國
    1 - 3 = 華人
    2 - 4 = 人民
    2 - 7 = 人民共和國
    4 - 6 = 共和
    4 - 7 = 共和國

    2.實現對專有名詞的識別和切分(人名,公司名)

    如:陳文平是開睿動力通訊科技有限公司董事長
    0 - 3 = 陳文平 <------ 人名,非漢語詞匯
    4 - 6 = 開睿 <------ 公司名,非漢語詞匯
    6 - 8 = 動力
    8 - 10 = 通訊
    10 - 12 = 科技
    12 - 14 = 有限
    12 - 16 = 有限公司
    14 - 16 = 公司
    16 - 18 = 董事
    16 - 19 = 董事長
    18 - 19 = 長

    3.對數詞和量詞的合理切分

    如:據路透社報道,印度尼西亞社會事務部一官員星期二(29日)表示,日惹市附近當地時間27日晨5時53分發生的里氏6.2級地震已經造成至少5427人死亡,20000余人受傷,近20萬人無家可歸。
    0 - 1 = 據
    1 - 4 = 路透社
    4 - 6 = 報道
    。。。。。。
    18 - 20 = 官員
    20 - 22 = 星期
    20 - 23 = 星期二
    22 - 23 = 二
    24 - 26 = 29
    24 - 27 = 29日
    26 - 27 = 日
    28 - 30 = 表示
    31 - 33 = 日惹
    33 - 34 = 市
    。。。。。。
    40 - 42 = 27
    40 - 43 = 27日
    43 - 44 = 晨
    44 - 45 = 5
    44 - 46 = 5時
    45 - 46 = 時
    46 - 48 = 53
    46 - 49 = 53分
    48 - 50 = 分發
    。。。。。。
    52 - 54 = 里氏
    54 - 57 = 6.2
    54 - 58 = 6.2級
    57 - 58 = 級
    58 - 60 = 地震
    。。。。。。
    66 - 70 = 5427
    66 - 71 = 5427人
    71 - 73 = 死亡
    72 - 73 = 亡
    74 - 79 = 20000
    79 - 81 = 余人
    81 - 83 = 受傷
    84 - 85 = 近
    85 - 87 = 20
    85 - 89 = 20萬人
    87 - 89 = 萬人
    89 - 93 = 無家可歸

    轉載于 http://www.jdon.com/jivejdon/thread/30255.html

    posted @ 2008-06-06 14:10 魯勝迪 閱讀(1104) | 評論 (0)編輯 收藏

    關于無刷新顯示實時數據庫程序問題

    現在實現的效果是,可以用1.jsp頁面調用2.jsp頁面,但是問題在于1.jsp頁面只能調用編譯后的2.jsp
    就是說,當我改變數據庫中相應內容的值以后,它就不能實現做出相應的改變了。
    但是當我將1.jsp和2.jsp運行時,這個問題就解決了,因為在2.jsp實現了自動刷新功能,它可以定時的去獲取數據庫的值。

    拋出問題:那是否可以在同一頁面中導入兩張jsp頁面,然后實現一個通過刷新實現對另一個不刷新頁面的更新呢?



    客戶端頁面代碼(1.jsp)如下

    <html>
     <head>
     <script language="javascript">
     
             var xmlHttp;

             function createXMLHttpRequest(){
                if (window.ActiveXObject){
                     xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
                }else if(window.XMLHttpRequest){
                     xmlHttp = new XMLHttpRequest();
                }
            }

       function re(){
                createXMLHttpRequest();      
                xmlHttp.open("GET","2.jsp",true);
                xmlHttp.onreadystatechange = callBack;
                xmlHttp.send(null);
              }
      
       function callBack(){
                if (xmlHttp.readyState == 4) {
                 if (xmlHttp.status == 200) {
                    var str = xmlHttp.responseText;
          t.innerHTML=str;
                   setTimeout('re()',1000);
                        }
                  }
             }

    </script>
    </head>
    <body onload="javascript:re();">
    <span id=t>123</span>
    </body>

    _____________________________________

    服務器端代碼(2.jsp)如下

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <jsp:directive.page import="java.sql.ResultSet"/>

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
     <meta http-equiv="Refresh" content="10">
      <jsp:useBean id="db"  scope="session" class="news.sql_data"/>
    <body>

    <%
     String sql="select * from hzt_task t where title='lsd' ";
      
     ResultSet rs=db.executeQuery(sql);
      
     //int i=0;
      
     while(rs.next()){

     // runpercent=rs.getString("runpercent");
         out.println(rs.getString("runpercent"));
      
     // i++;
     }
     %>
    </body>
    </html>

    posted @ 2008-06-02 15:56 魯勝迪 閱讀(1035) | 評論 (1)編輯 收藏

    javascript傳值給jsp 簡單實例

    <body>
    <div id='aa'>
    sdfdsfdsf
    <input name="" type="button" onclick="aa();"/>
    </div>
    <script language="javascript">
     function aa(){
      document.getElementById('aa').innerHTML='123123';
     }
    </script>
    </body>

    posted @ 2008-05-19 15:16 魯勝迪 閱讀(4476) | 評論 (4)編輯 收藏

    oracle數據庫的備份與還原(本地及遠程操作)

         摘要: 備份,在開始運行中CMD
    exp ay_user/ay@zhf file=e:\名稱.dmp log=e:\log.txt full=y

    //ay_user 用戶名 zhf 密碼 要備份的數據庫名和地址,log=e:\log.txt 備份生成的日志文件的地址和名稱。full=y完全備份

    還原,在開始運行中CMD
    imp zhf/huifeng@zhf file=f:\名稱.dmp log=f:\log.txt full=y   閱讀全文

    posted @ 2008-05-11 10:27 魯勝迪 閱讀(5308) | 評論 (0)編輯 收藏

    動態顯示進度條


    可以將下邊的代碼嵌入到html,jsp,asp,php或aspx文件中!


    截圖


    代碼如下:

    <body>
    <input type="button" value="start" onclick="processBar.changeMode();if(processBar.isMoving){this.value='Stop';}else{this.value='Start';}">
    </body>

    <script>
    if(window.ActiveXObject) document.execCommand("BackgroundImageCache",false,true);

    function ProcessBar(){
        this.width = 256;
        this.height = 18;
        this.top = 0;
        this.left = 0;
        this.backImg = "process_back.gif";
        this.foreImg = "process.gif";
        this.backDiv = document.createElement("div");
        this.foreDiv = document.createElement("div");
        this.fontDiv = document.createElement("div");

        this.isMoving = false;
        this.nowLength = 0;
        this.moveInterval = 100;
        this.moveRange = 1;
        this.timer;

        ProcessBar.nowObj = this;

        this.init = function(){
             this.foreDiv.style.backgroundImage = "url(" + this.foreImg + ")";
             this.foreDiv.style.backgroundRepeat = "no-repeat";
             this.foreDiv.style.position = "absolute";
             this.foreDiv.style.width = this.nowLength;
             this.foreDiv.style.height = this.height;
             this.foreDiv.style.top = 0;
             this.foreDiv.style.left = 0;
           
             this.fontDiv.style.background = "transparent";
             this.fontDiv.style.position = "absolute";
             this.fontDiv.style.width = this.width;
             this.fontDiv.style.height = this.height;
             this.fontDiv.style.top = 2;
             this.fontDiv.style.left = 0;
             this.fontDiv.style.textAlign = "center";
             this.fontDiv.style.fontSize = "13px";
             this.fontDiv.appendChild(document.createTextNode(" "));

             this.backDiv.style.backgroundImage = "url(" + this.backImg + ")";
             this.backDiv.style.backgroundRepeat = "no-repeat";
             this.backDiv.style.position = "absolute";
             this.backDiv.style.width = this.width;
             this.backDiv.style.height = this.height;
             this.backDiv.style.top = this.top;
             this.backDiv.style.left = this.left;

             this.backDiv.appendChild(this.foreDiv);
             this.backDiv.appendChild(this.fontDiv);

             document.body.appendChild(this.backDiv);
        }

        this.changeMode = function(){
             this.isMoving = !this.isMoving;
           
             if(this.isMoving){
                 this.timer = window.setInterval(ProcessBar.nowObj.moving, this.moveInterval);
             }else{
                 window.clearInterval(this.timer);
             }
        }

        this.moving = function(){
             ProcessBar.nowObj.nowLength += ProcessBar.nowObj.moveRange;
             ProcessBar.nowObj.foreDiv.style.width = ProcessBar.nowObj.nowLength;

             ProcessBar.nowObj.fontDiv.firstChild.data = Math.ceil((ProcessBar.nowObj.nowLength/ProcessBar.nowObj.width )*100) + "%";

             if(ProcessBar.nowObj.nowLength >= ProcessBar.nowObj.width ){
                 window.clearInterval(ProcessBar.nowObj.timer);
                 ProcessBar.nowObj.fontDiv.firstChild.data = "Complete!";
             }
        }

      
    }

    var processBar = new ProcessBar();
    processBar.backImg = "http://screenprint2007.cpp114.com/UserFiles/20070412155452218.gif";
    processBar.foreImg = "http://screenprint2007.cpp114.com/UserFiles/20070412155424937.gif";
    processBar.top = 100;
    processBar.left = 20;
    processBar.init();
    </script>

    posted @ 2008-05-10 09:34 魯勝迪 閱讀(425) | 評論 (0)編輯 收藏

    oracle創建表空間,創建用戶以及授權

    //創建臨時表空間

    create temporary tablespace test_temp
    tempfile 'E:\oracle\product\10.2.0\oradata\testserver\test_temp01.dbf'
    size 32m
    autoextend on
    next 32m maxsize 2048m
    extent management local;

    //創建數據表空間
    create tablespace test_data
    logging
    datafile 'E:\oracle\product\10.2.0\oradata\testserver\test_data01.dbf'
    size 32m
    autoextend on
    next 32m maxsize 2048m
    extent management local;

    //創建用戶并指定表空間
    create user testserver_user identified by testserver_user
    default tablespace test_data
    temporary tablespace test_temp;

    //給用戶授予權限

    grant connect,resource to testserver_user;

    //以后以該用戶登錄,創建的任何數據庫對象都屬于test_temp 和test_data表空間,這就不用在每創建一個對象給其指定表空間了。

    posted @ 2008-05-09 20:15 魯勝迪 閱讀(21088) | 評論 (12)編輯 收藏

    遠程操作、遠程協助

    在使用電腦的過程中,我們會遇到各種各樣的問題。在那些自己不能獨立解決的問題面前,我們只能求助于專業的技術人員或者找經驗豐富的朋友幫忙。可是技術人員不可能時時都在身邊,那還有沒有其他辦法可以得到技術人員的協助呢?

      微軟早就為我們在Windows XP中內置了一個通過網絡的遠程協助工具:“遠程桌面連接”。通過遠程桌面連接我們可以控制其他安裝了Windows XP、Windows 2000或者Windows Server 2003的計算機。在客戶計算機上選擇:開始|所有程序|附件|通信|遠程桌面連接,在彈出的對話框中輸入你要遠程連接的計算機的IP地址(如圖1所示)。如果對方允許你連接的話,就可以控制對方系統,就好像你正坐在對方的計算機前操作對方計算機的鍵盤和鼠標一樣。

     

    圖1 連接遠程桌面

      相對的,我們也可以設置Windows XP使得其他人可以遠程控制我們的計算機。在“我的電腦”上點擊右鍵,選擇“屬性”然后在彈出的對話框中選擇“遠程”,然后選中“遠程桌面”(如圖所示),之后選擇“選擇遠程用戶”在其中輸入可以訪問的用戶名。這樣其他用戶就可以遠程控制你的計算機,以便可以遠程幫你解決問題。

     

    圖2 開啟遠程桌面

      Windows XP中的遠程連接允許我們可以從技術人員和朋友那里得到遠程協助,這些用戶可以在你允許的時間內遠程控制你的計算機,并且他們的一切動作都是在你的監視之下的。當然為了得到遠程協助你還需要在網絡防火墻中開放3389端口。

    posted @ 2008-05-05 15:12 魯勝迪 閱讀(270) | 評論 (0)編輯 收藏

    oracle 自增變量設置

    將表t_uaer的字段ID設置為自增:(用序列sequence的方法來實現)

    ----創建表
    Create  table  t_user(
    Id number(6),userid varchar2(20),loginpassword varchar2(20),isdisable number(6)
    );

    ----創建序列
    create sequence user_seq
    increment by 1 
    start with 1
    nomaxvalue
    nominvalue
    nocache

    ----創建觸發器
    create or  replace trigger tr_user
    before insert on t_user
    for each row
    begin
    select user_seq.nextval into :new.id from dual;
    end;

    ----測試
    insert into t_user(userid,loginpassword, isdisable)
    values('ffll','liudddyujj', 0);
    insert into t_user(userid,loginpassword, isdisable)
    values('dddd','zhang', 0)
    select * from t_user;
    就可以看出結果。

    ***********************************************************************
    對sequence說明:
    increment by :用于指定序列增量(默認值:1),如果指定的是正整數,則序列號自動遞增,如果指定的是負數,則自動遞減。
    start with :用于指定序列生成器生成的第一個序列號,當序列號順序遞增時默認值為序列號的最小值 當序列號順序遞減時默認值為序列號的最大值。
    Maxvalue:用于指定序列生成器可以生成的組大序列號(必須大于或等于start with,并且必須大于minvalue),默認為nomaxvalue。
    Minvalue:用于指定序列生成器可以生成的最小序列號(必須小于或等于starr with,并且必須小于maxvalue),默認值為nominvalue。
    Cycle:用于指定在達到序列的最大值或最小值之后是否繼續生成序列號,默認為nocycle。
    Cache:用于指定在內存中可以預分配的序列號個數(默認值:20)。
    在sequence中應注意:
    1、 第一次NEXTVAL返回的是初始值;隨后的NEXTVAL會自動增加你定義的INCREMENT BY值,然后返回增加后的值。CURRVAL 總是返回當前SEQUENCE的值,但是在第一次NEXTVAL初始化之后才能使用CURRVAL,否則會出錯。一次NEXTVAL會增加一次SEQUENCE的值,所以如果你在同一個語句里面使用多個NEXTVAL,其值就是不一樣的。
    2、 如果指定CACHE值,ORACLE就可以預先在內存里面放置一些sequence,這樣存取的快些。cache里面的取完后,oracle自動再取一組到cache。 使用cache或許會跳號, 比如數據庫突然不正常down掉(shutdown abort),cache中的sequence就會丟失. 所以可以在create sequence的時候用nocache防止這種情況。


    關鍵字:自增    sequence序列    increment    start with

    posted @ 2008-04-14 13:13 魯勝迪 閱讀(3236) | 評論 (0)編輯 收藏

    Lucene:基于Java的全文檢索引擎簡介【轉】

    http://www.chedong.com/tech/lucene.html



    Lucene是一個基于Java的全文索引工具包。

    1. 基于Java的全文索引引擎Lucene簡介:關于作者和Lucene的歷史
    2. 全文檢索的實現:Luene全文索引和數據庫索引的比較
    3. 中文切分詞機制簡介:基于詞庫和自動切分詞算法的比較
    4. 具體的安裝和使用簡介:系統結構介紹和演示
    5. Hacking Lucene:簡化的查詢分析器,刪除的實現,定制的排序,應用接口的擴展
    6. 從Lucene我們還可以學到什么

    基于Java的全文索引/檢索引擎——Lucene

    Lucene不是一個完整的全文索引應用,而是是一個用Java寫的全文索引引擎工具包,它可以方便的嵌入到各種應用中實現針對應用的全文索引/檢索功能。

    Lucene的作者:Lucene的貢獻者Doug Cutting是一位資深全文索引/檢索專家,曾經是V-Twin搜索引擎(Apple的Copland操作系統的成就之一)的主要開發者,后在Excite擔任高級系統架構設計師,目前從事于一些INTERNET底層架構的研究。他貢獻出的Lucene的目標是為各種中小型應用程序加入全文檢索功能。

    Lucene的發展歷程:早先發布在作者自己的www.lucene.com,后來發布在SourceForge,2001年年底成為APACHE基金會jakarta的一個子項目:http://jakarta.apache.org/lucene/

    已經有很多Java項目都使用了Lucene作為其后臺的全文索引引擎,比較著名的有:

    • Jive:WEB論壇系統;
    • Eyebrows:郵件列表HTML歸檔/瀏覽/查詢系統,本文的主要參考文檔“TheLucene search engine: Powerful, flexible, and free”作者就是EyeBrows系統的主要開發者之一,而EyeBrows已經成為目前APACHE項目的主要郵件列表歸檔系統。
    • Cocoon:基于XML的web發布框架,全文檢索部分使用了Lucene
    • Eclipse:基于Java的開放開發平臺,幫助部分的全文索引使用了Lucene

    對于中文用戶來說,最關心的問題是其是否支持中文的全文檢索。但通過后面對于Lucene的結構的介紹,你會了解到由于Lucene良好架構設計,對中文的支持只需對其語言詞法分析接口進行擴展就能實現對中文檢索的支持。

    全文檢索的實現機制

    Lucene的API接口設計的比較通用,輸入輸出結構都很像數據庫的表==>記錄==>字段,所以很多傳統的應用的文件、數據庫等都可以比較方便的映射到Lucene的存儲結構/接口中。總體上看:可以先把Lucene當成一個支持全文索引的數據庫系統

    比較一下Lucene和數據庫:

    Lucene 數據庫
    索引數據源:doc(field1,field2...) doc(field1,field2...)
    \ indexer /
    _____________
    | Lucene Index|
    --------------
    / searcher \
    結果輸出:Hits(doc(field1,field2) doc(field1...))
     索引數據源:record(field1,field2...) record(field1..)
    \ SQL: insert/
    _____________
    | DB Index |
    -------------
    / SQL: select \
    結果輸出:results(record(field1,field2..) record(field1...))
    Document:一個需要進行索引的“單元”
    一個Document由多個字段組成
    Record:記錄,包含多個字段
    Field:字段 Field:字段
    Hits:查詢結果集,由匹配的Document組成 RecordSet:查詢結果集,由多個Record組成

    全文檢索 ≠ like "%keyword%"

    通常比較厚的書籍后面常常附關鍵詞索引表(比如:北京:12, 34頁,上海:3,77頁……),它能夠幫助讀者比較快地找到相關內容的頁碼。而數據庫索引能夠大大提高查詢的速度原理也是一樣,想像一下通過書后面的索引查找的速度要比一頁一頁地翻內容高多少倍……而索引之所以效率高,另外一個原因是它是排好序的。對于檢索系統來說核心是一個排序問題

    由于數據庫索引不是為全文索引設計的,因此,使用like "%keyword%"時,數據庫索引是不起作用的,在使用like查詢時,搜索過程又變成類似于一頁頁翻書的遍歷過程了,所以對于含有模糊查詢的數據庫服務來說,LIKE對性能的危害是極大的。如果是需要對多個關鍵詞進行模糊匹配:like"%keyword1%" and like "%keyword2%" ...其效率也就可想而知了。

    所以建立一個高效檢索系統的關鍵是建立一個類似于科技索引一樣的反向索引機制,將數據源(比如多篇文章)排序順序存儲的同時,有另外一個排好序的關鍵詞列表,用于存儲關鍵詞==>文章映射關系,利用這樣的映射關系索引:[關鍵詞==>出現關鍵詞的文章編號,出現次數(甚至包括位置:起始偏移量,結束偏移量),出現頻率],檢索過程就是把模糊查詢變成多個可以利用索引的精確查詢的邏輯組合的過程。從而大大提高了多關鍵詞查詢的效率,所以,全文檢索問題歸結到最后是一個排序問題。

    由此可以看出模糊查詢相對數據庫的精確查詢是一個非常不確定的問題,這也是大部分數據庫對全文檢索支持有限的原因。Lucene最核心的特征是通過特殊的索引結構實現了傳統數據庫不擅長的全文索引機制,并提供了擴展接口,以方便針對不同應用的定制。

    可以通過一下表格對比一下數據庫的模糊查詢:

      Lucene全文索引引擎 數據庫
    索引 將數據源中的數據都通過全文索引一一建立反向索引 對于LIKE查詢來說,數據傳統的索引是根本用不上的。數據需要逐個便利記錄進行GREP式的模糊匹配,比有索引的搜索速度要有多個數量級的下降。
    匹配效果 通過詞元(term)進行匹配,通過語言分析接口的實現,可以實現對中文等非英語的支持。 使用:like "%net%" 會把netherlands也匹配出來,
    多個關鍵詞的模糊匹配:使用like "%com%net%":就不能匹配詞序顛倒的xxx.net..xxx.com
    匹配度 有匹配度算法,將匹配程度(相似度)比較高的結果排在前面。 沒有匹配程度的控制:比如有記錄中net出現5詞和出現1次的,結果是一樣的。
    結果輸出 通過特別的算法,將最匹配度最高的頭100條結果輸出,結果集是緩沖式的小批量讀取的。 返回所有的結果集,在匹配條目非常多的時候(比如上萬條)需要大量的內存存放這些臨時結果集。
    可定制性 通過不同的語言分析接口實現,可以方便的定制出符合應用需要的索引規則(包括對中文的支持) 沒有接口或接口復雜,無法定制
    結論 高負載的模糊查詢應用,需要負責的模糊查詢的規則,索引的資料量比較大 使用率低,模糊匹配規則簡單或者需要模糊查詢的資料量少

    全文檢索和數據庫應用最大的不同在于:讓最相關的頭100條結果滿足98%以上用戶的需求

    Lucene的創新之處:

    大部分的搜索(數據庫)引擎都是用B樹結構來維護索引,索引的更新會導致大量的IO操作,Lucene在實現中,對此稍微有所改進:不是維護一個索引文件,而是在擴展索引的時候不斷創建新的索引文件,然后定期的把這些新的小索引文件合并到原先的大索引中(針對不同的更新策略,批次的大小可以調整),這樣在不影響檢索的效率的前提下,提高了索引的效率。

    Lucene和其他一些全文檢索系統/應用的比較:

      Lucene 其他開源全文檢索系統
    增量索引和批量索引 可以進行增量的索引(Append),可以對于大量數據進行批量索引,并且接口設計用于優化批量索引和小批量的增量索引。 很多系統只支持批量的索引,有時數據源有一點增加也需要重建索引。
    數據源 Lucene沒有定義具體的數據源,而是一個文檔的結構,因此可以非常靈活的適應各種應用(只要前端有合適的轉換器把數據源轉換成相應結構), 很多系統只針對網頁,缺乏其他格式文檔的靈活性。
    索引內容抓取 Lucene的文檔是由多個字段組成的,甚至可以控制那些字段需要進行索引,那些字段不需要索引,近一步索引的字段也分為需要分詞和不需要分詞的類型:
       需要進行分詞的索引,比如:標題,文章內容字段
       不需要進行分詞的索引,比如:作者/日期字段
    缺乏通用性,往往將文檔整個索引了
    語言分析 通過語言分析器的不同擴展實現:
    可以過濾掉不需要的詞:an the of 等,
    西文語法分析:將jumps jumped jumper都歸結成jump進行索引/檢索
    非英文支持:對亞洲語言,阿拉伯語言的索引支持
    缺乏通用接口實現
    查詢分析 通過查詢分析接口的實現,可以定制自己的查詢語法規則:
    比如: 多個關鍵詞之間的 + - and or關系等
     
    并發訪問 能夠支持多用戶的使用  

     

    關于亞洲語言的的切分詞問題(Word Segment)

    對于中文來說,全文索引首先還要解決一個語言分析的問題,對于英文來說,語句中單詞之間是天然通過空格分開的,但亞洲語言的中日韓文語句中的字是一個字挨一個,所有,首先要把語句中按“詞”進行索引的話,這個詞如何切分出來就是一個很大的問題。

    首先,肯定不能用單個字符作(si-gram)為索引單元,否則查“上海”時,不能讓含有“海上”也匹配。

    但一句話:“北京天安門”,計算機如何按照中文的語言習慣進行切分呢?
    “北京 天安門” 還是“北 京 天安門”?讓計算機能夠按照語言習慣進行切分,往往需要機器有一個比較豐富的詞庫才能夠比較準確的識別出語句中的單詞。

    另外一個解決的辦法是采用自動切分算法:將單詞按照2元語法(bigram)方式切分出來,比如:
    "北京天安門" ==> "北京 京天 天安 安門"。

    這樣,在查詢的時候,無論是查詢"北京" 還是查詢"天安門",將查詢詞組按同樣的規則進行切分:"北京","天安安門",多個關鍵詞之間按與"and"的關系組合,同樣能夠正確地映射到相應的索引中。這種方式對于其他亞洲語言:韓文,日文都是通用的。

    基于自動切分的最大優點是沒有詞表維護成本,實現簡單,缺點是索引效率低,但對于中小型應用來說,基于2元語法的切分還是夠用的。基于2元切分后的索引一般大小和源文件差不多,而對于英文,索引文件一般只有原文件的30%-40%不同,


    自動切分 詞表切分
    實現 實現非常簡單 實現復雜
    查詢 增加了查詢分析的復雜程度, 適于實現比較復雜的查詢語法規則
    存儲效率 索引冗余大,索引幾乎和原文一樣大 索引效率高,為原文大小的30%左右
    維護成本 無詞表維護成本 詞表維護成本非常高:中日韓等語言需要分別維護。
    還需要包括詞頻統計等內容
    適用領域 嵌入式系統:運行環境資源有限
    分布式系統:無詞表同步問題
    多語言環境:無詞表維護成本
    對查詢和存儲效率要求高的專業搜索引擎

    目前比較大的搜索引擎的語言分析算法一般是基于以上2個機制的結合。關于中文的語言分析算法,大家可以在Google查關鍵詞"wordsegment search"能找到更多相關的資料。

    安裝和使用

    下載:http://jakarta.apache.org/lucene/

    注意:Lucene中的一些比較復雜的詞法分析是用JavaCC生成的(JavaCC:JavaCompilerCompiler,純Java的詞法分析生成器),所以如果從源代碼編譯或需要修改其中的QueryParser、定制自己的詞法分析器,還需要從https://javacc.dev.java.net/下載javacc。

    lucene的組成結構:對于外部應用來說索引模塊(index)和檢索模塊(search)是主要的外部應用入口

    org.apache.Lucene.search/ 搜索入口
    org.apache.Lucene.index/ 索引入口
    org.apache.Lucene.analysis/ 語言分析器
    org.apache.Lucene.queryParser/ 查詢分析器
    org.apache.Lucene.document/ 存儲結構
    org.apache.Lucene.store/  底層IO/存儲結構
    org.apache.Lucene.util/ 一些公用的數據結構

    簡單的例子演示一下Lucene的使用方法:

    索引過程:從命令行讀取文件名(多個),將文件分路徑(path字段)和內容(body字段)2個字段進行存儲,并對內容進行全文索引:索引的單位是Document對象,每個Document對象包含多個字段Field對象,針對不同的字段屬性和數據輸出的需求,對字段還可以選擇不同的索引/存儲字段規則,列表如下:
    方法 切詞 索引 存儲 用途
    Field.Text(String name, String value) Yes Yes Yes 切分詞索引并存儲,比如:標題,內容字段
    Field.Text(String name, Reader value) Yes Yes No 切分詞索引不存儲,比如:META信息,
    不用于返回顯示,但需要進行檢索內容
    Field.Keyword(String name, String value) No Yes Yes 不切分索引并存儲,比如:日期字段
    Field.UnIndexed(String name, String value) No No Yes 不索引,只存儲,比如:文件路徑
    Field.UnStored(String name, String value) Yes Yes No 只全文索引,不存儲
    public class IndexFiles { 
    //使用方法:: IndexFiles [索引輸出目錄] [索引的文件列表] ...
    public static void main(String[] args) throws Exception {
    String indexPath = args[0];
    IndexWriter writer;
    //用指定的語言分析器構造一個新的寫索引器(第3個參數表示是否為追加索引)
    writer = new IndexWriter(indexPath, new SimpleAnalyzer(), false);

    for (int i=1; i<args.length; i++) {
    System.out.println("Indexing file " + args[i]);
    InputStream is = new FileInputStream(args[i]);

    //構造包含2個字段Field的Document對象
    //一個是路徑path字段,不索引,只存儲
    //一個是內容body字段,進行全文索引,并存儲
    Document doc = new Document();
    doc.add(Field.UnIndexed("path", args[i]));
    doc.add(Field.Text("body", (Reader) new InputStreamReader(is)));
    //將文檔寫入索引
    writer.addDocument(doc);
    is.close();
    };
    //關閉寫索引器
    writer.close();
    }
    }
     

    索引過程中可以看到:

    • 語言分析器提供了抽象的接口,因此語言分析(Analyser)是可以定制的,雖然lucene缺省提供了2個比較通用的分析器SimpleAnalyser和StandardAnalyser,這2個分析器缺省都不支持中文,所以要加入對中文語言的切分規則,需要修改這2個分析器。
    • Lucene并沒有規定數據源的格式,而只提供了一個通用的結構(Document對象)來接受索引的輸入,因此輸入的數據源可以是:數據庫,WORD文檔,PDF文檔,HTML文檔……只要能夠設計相應的解析轉換器將數據源構造成成Docuement對象即可進行索引。
    • 對于大批量的數據索引,還可以通過調整IndexerWrite的文件合并頻率屬性(mergeFactor)來提高批量索引的效率。

    檢索過程和結果顯示:

    搜索結果返回的是Hits對象,可以通過它再訪問Document==>Field中的內容。

    假設根據body字段進行全文檢索,可以將查詢結果的path字段和相應查詢的匹配度(score)打印出來,

    public class Search { 
    public static void main(String[] args) throws Exception {
    String indexPath = args[0], queryString = args[1];
    //指向索引目錄的搜索器
    Searcher searcher = new IndexSearcher(indexPath);
    //查詢解析器:使用和索引同樣的語言分析器
    Query query = QueryParser.parse(queryString, "body",
    new SimpleAnalyzer());
    //搜索結果使用Hits存儲
    Hits hits = searcher.search(query);
    //通過hits可以訪問到相應字段的數據和查詢的匹配度
    for (int i=0; i<hits.length(); i++) {
    System.out.println(hits.doc(i).get("path") + "; Score: " +
    hits.score(i));
    };
    }
    }
    在整個檢索過程中,語言分析器,查詢分析器,甚至搜索器(Searcher)都是提供了抽象的接口,可以根據需要進行定制。

    Hacking Lucene

    簡化的查詢分析器

    個人感覺lucene成為JAKARTA項目后,畫在了太多的時間用于調試日趨復雜QueryParser,而其中大部分是大多數用戶并不很熟悉的,目前LUCENE支持的語法:

    Query ::= ( Clause )*
    Clause ::= ["+", "-"] [<TERM> ":"] ( <TERM> | "(" Query ")")

    中間的邏輯包括:and or + - &&||等符號,而且還有"短語查詢"和針對西文的前綴/模糊查詢等,個人感覺對于一般應用來說,這些功能有一些華而不實,其實能夠實現目前類似于Google的查詢語句分析功能其實對于大多數用戶來說已經夠了。所以,Lucene早期版本的QueryParser仍是比較好的選擇。

    添加修改刪除指定記錄(Document)

    Lucene提供了索引的擴展機制,因此索引的動態擴展應該是沒有問題的,而指定記錄的修改也似乎只能通過記錄的刪除,然后重新加入實現。如何刪除指定的記錄呢?刪除的方法也很簡單,只是需要在索引時根據數據源中的記錄ID專門另建索引,然后利用IndexReader.delete(Termterm)方法通過這個記錄ID刪除相應的Document。

    根據某個字段值的排序功能

    lucene缺省是按照自己的相關度算法(score)進行結果排序的,但能夠根據其他字段進行結果排序是一個在LUCENE的開發郵件列表中經常提到的問題,很多原先基于數據庫應用都需要除了基于匹配度(score)以外的排序功能。而從全文檢索的原理我們可以了解到,任何不基于索引的搜索過程效率都會導致效率非常的低,如果基于其他字段的排序需要在搜索過程中訪問存儲字段,速度回大大降低,因此非常是不可取的。

    但這里也有一個折中的解決方法:在搜索過程中能夠影響排序結果的只有索引中已經存儲的docID和score這2個參數,所以,基于score以外的排序,其實可以通過將數據源預先排好序,然后根據docID進行排序來實現。這樣就避免了在LUCENE搜索結果外對結果再次進行排序和在搜索過程中訪問不在索引中的某個字段值。

    這里需要修改的是IndexSearcher中的HitCollector過程:

    ...
     scorer.score(new HitCollector() {
    private float minScore = 0.0f;
    public final void collect(int doc, float score) {
    if (score > 0.0f && // ignore zeroed buckets
    (bits==null || bits.get(doc))) { // skip docs not in bits
    totalHits[0]++;
    if (score >= minScore) {
    /* 原先:Lucene將docID和相應的匹配度score例入結果命中列表中:
    * hq.put(new ScoreDoc(doc, score)); // update hit queue
    * 如果用doc 或 1/doc 代替 score,就實現了根據docID順排或逆排
    * 假設數據源索引時已經按照某個字段排好了序,而結果根據docID排序也就實現了
    * 針對某個字段的排序,甚至可以實現更復雜的score和docID的擬合。
    */
    hq.put(new ScoreDoc(doc, (float) 1/doc ));
    if (hq.size() > nDocs) { // if hit queue overfull
    hq.pop(); // remove lowest in hit queue
    minScore = ((ScoreDoc)hq.top()).score; // reset minScore
    }
    }
    }
    }
    }, reader.maxDoc());

    更通用的輸入輸出接口

    雖然lucene沒有定義一個確定的輸入文檔格式,但越來越多的人想到使用一個標準的中間格式作為Lucene的數據導入接口,然后其他數據,比如PDF只需要通過解析器轉換成標準的中間格式就可以進行數據索引了。這個中間格式主要以XML為主,類似實現已經不下4,5個:

    數據源: WORD       PDF     HTML    DB       other
    \ | | | /
    XML中間格式
    |
    Lucene INDEX

    目前還沒有針對MSWord文檔的解析器,因為Word文檔和基于ASCII的RTF文檔不同,需要使用COM對象機制解析。這個是我在Google上查的相關資料:http://www.intrinsyc.com/products/enterprise_applications.asp
    另外一個辦法就是把Word文檔轉換成text:http://www.winfield.demon.nl/index.html


    索引過程優化

    索引一般分2種情況,一種是小批量的索引擴展,一種是大批量的索引重建。在索引過程中,并不是每次新的DOC加入進去索引都重新進行一次索引文件的寫入操作(文件I/O是一件非常消耗資源的事情)。

    Lucene先在內存中進行索引操作,并根據一定的批量進行文件的寫入。這個批次的間隔越大,文件的寫入次數越少,但占用內存會很多。反之占用內存少,但文件IO操作頻繁,索引速度會很慢。在IndexWriter中有一個MERGE_FACTOR參數可以幫助你在構造索引器后根據應用環境的情況充分利用內存減少文件的操作。根據我的使用經驗:缺省Indexer是每20條記錄索引后寫入一次,每將MERGE_FACTOR增加50倍,索引速度可以提高1倍左右。

    搜索過程優化

    lucene支持內存索引:這樣的搜索比基于文件的I/O有數量級的速度提升。
    http://www.onjava.com/lpt/a/3273
    而盡可能減少IndexSearcher的創建和對搜索結果的前臺的緩存也是必要的。

    Lucene面向全文檢索的優化在于首次索引檢索后,并不把所有的記錄(Document)具體內容讀取出來,而起只將所有結果中匹配度最高的頭100條結果(TopDocs)的ID放到結果集緩存中并返回,這里可以比較一下數據庫檢索:如果是一個10,000條的數據庫檢索結果集,數據庫是一定要把所有記錄內容都取得以后再開始返回給應用結果集的。所以即使檢索匹配總數很多,Lucene的結果集占用的內存空間也不會很多。對于一般的模糊檢索應用是用不到這么多的結果的,頭100條已經可以滿足90%以上的檢索需求。

    如果首批緩存結果數用完后還要讀取更后面的結果時Searcher會再次檢索并生成一個上次的搜索緩存數大1倍的緩存,并再重新向后抓取。所以如果構造一個Searcher去查1-120條結果,Searcher其實是進行了2次搜索過程:頭100條取完后,緩存結果用完,Searcher重新檢索再構造一個200條的結果緩存,依此類推,400條緩存,800條緩存。由于每次Searcher對象消失后,這些緩存也訪問那不到了,你有可能想將結果記錄緩存下來,緩存數盡量保證在100以下以充分利用首次的結果緩存,不讓Lucene浪費多次檢索,而且可以分級進行結果緩存。

    Lucene的另外一個特點是在收集結果的過程中將匹配度低的結果自動過濾掉了。這也是和數據庫應用需要將搜索的結果全部返回不同之處。

    我的一些嘗試

    • 支持中文的Tokenizer:這里有2個版本,一個是通過JavaCC生成的,對CJK部分按一個字符一個TOKEN索引,另外一個是從SimpleTokenizer改寫的,對英文支持數字和字母TOKEN,對中文按迭代索引。
    • 基于XML數據源的索引器:XMLIndexer,因此所有數據源只要能夠按照DTD轉換成指定的XML,就可以用XMLIndxer進行索引了。
    • 根據某個字段排序:按記錄索引順序排序結果的搜索器:IndexOrderSearcher,因此如果需要讓搜索結果根據某個字段排序,可以讓數據源先按某個字段排好序(比如:PriceField),這樣索引后,然后在利用這個按記錄的ID順序檢索的搜索器,結果就是相當于是那個字段排序的結果了。

    從Lucene學到更多

    Luene的確是一個面對對象設計的典范

    • 所有的問題都通過一個額外抽象層來方便以后的擴展和重用:你可以通過重新實現來達到自己的目的,而對其他模塊而不需要;
    • 簡單的應用入口Searcher, Indexer,并調用底層一系列組件協同的完成搜索任務;
    • 所有的對象的任務都非常專一:比如搜索過程:QueryParser分析將查詢語句轉換成一系列的精確查詢的組合(Query),通過底層的索引讀取結構IndexReader進行索引的讀取,并用相應的打分器給搜索結果進行打分/排序等。所有的功能模塊原子化程度非常高,因此可以通過重新實現而不需要修改其他模塊。 
    • 除了靈活的應用接口設計,Lucene還提供了一些適合大多數應用的語言分析器實現(SimpleAnalyser,StandardAnalyser),這也是新用戶能夠很快上手的重要原因之一。

    這些優點都是非常值得在以后的開發中學習借鑒的。作為一個通用工具包,Lunece的確給予了需要將全文檢索功能嵌入到應用中的開發者很多的便利。

    此外,通過對Lucene的學習和使用,我也更深刻地理解了為什么很多數據庫優化設計中要求,比如:

    • 盡可能對字段進行索引來提高查詢速度,但過多的索引會對數據庫表的更新操作變慢,而對結果過多的排序條件,實際上往往也是性能的殺手之一。
    • 很多商業數據庫對大批量的數據插入操作會提供一些優化參數,這個作用和索引器的merge_factor的作用是類似的,
    • 20%/80%原則:查的結果多并不等于質量好,尤其對于返回結果集很大,如何優化這頭幾十條結果的質量往往才是最重要的。
    • 盡可能讓應用從數據庫中獲得比較小的結果集,因為即使對于大型數據庫,對結果集的隨機訪問也是一個非常消耗資源的操作。

    參考資料:

    Apache: Lucene Project
    http://jakarta.apache.org/lucene/
    Lucene開發/用戶郵件列表歸檔
    Lucene-dev@jakarta.apache.org
    Lucene-user@jakarta.apache.org

    The Lucene search engine: Powerful, flexible, and free
    http://www.javaworld.com/javaworld/jw-09-2000/jw-0915-Lucene_p.html

    Lucene Tutorial
    http://www.darksleep.com/puff/lucene/lucene.html

    Notes on distributed searching with Lucene
    http://home.clara.net/markharwood/lucene/

    中文語言的切分詞
    http://www.google.com/search?sourceid=navclient&hl=zh-CN&q=chinese+word+segment

    搜索引擎工具介紹
    http://searchtools.com/

    Lucene作者Cutting的幾篇論文和專利
    http://lucene.sourceforge.net/publications.html 

    Lucene的.NET實現:dotLucene
    http://sourceforge.net/projects/dotlucene/

    Lucene作者Cutting的另外一個項目:基于Java的搜索引擎Nutch
    http://www.nutch.org/   http://sourceforge.net/projects/nutch/

    關于基于詞表和N-Gram的切分詞比較
    http://china.nikkeibp.co.jp/cgi-bin/china/news/int/int200302100112.html

    2005-01-08 Cutting在Pisa大學做的關于Lucene的講座:非常詳細的Lucene架構解說

    特別感謝:
    前網易CTO許良杰(Jack Xu)給我的指導:是您將我帶入了搜索引擎這個行業。

    posted @ 2008-04-10 13:52 魯勝迪 閱讀(197) | 評論 (0)編輯 收藏

    lucene多字段查詢

    http://hi.baidu.com/%B3%BF%D1%F4%C2%FE%B2%BD/blog/item/9478602deaa1cd37349bf7d5.html


    我的例子就是2.0的,現在給你的是兩個域,你可以用n個域

    BooleanQuery typeNegativeSearch = new BooleanQuery();
    QueryParser parser = new QueryParser("contents", new Analyzer());
                    parser.setDefaultOperator(QueryParser.AND_OPERATOR);
                    query = parser.parse(queryString);
                    QueryParser parser2 = new QueryParser("adISELL", new Analyzer());  

               
                    query2 = parser2.parse("\"2\"");  
    QueryParser parser3 = new QueryParser("adISELL", new Analyzer());              
                    query3 = parser3.parse("\"2\"");             
    QueryParser parser4 = new QueryParser("adISELL", new Analyzer());              
                    query4 = parser4.parse("\"2\"");             
    QueryParser parser4 = new QueryParser("adISELL", new Analyzer());              
                    query4 = parser4.parse("\"2\"");  
    。。。。
         QueryParser parser..n = new QueryParser("adISELL", new Analyzer());           

      
                    query..n = parser..n.parse("\"2\"");  
                    
                    typeNegativeSearch.add(query,Occur.MUST);
                    typeNegativeSearch.add(query2,Occur.MUST);
    typeNegativeSearch.add(query3,Occur.MUST);
                    typeNegativeSearch.add(query4,Occur.MUST);
    .....
    typeNegativeSearch.add(query..n,Occur.MUST);

    hits = searcher.search(typeNegativeSearch);

     

    1, 幾種span的querySpanTermQuery:檢索效果完全同TermQuery,但內部會記錄一些位置信息

    ,供SpanQuery的其它API使用,是其它屬于SpanQuery的Query的基礎。
    SpanFirstQuery:查找方式為從Field的內容起始位置開始,在一個固定的寬度內查找所指定的

    詞條。
    SpanNearQuery:功能類似PharaseQuery。SpanNearQuery查找所匹配的不一定是短語,還有可

    能是另一個SpanQuery的查詢結果作為整體考慮,進行嵌套查詢。
    SpanOrQuery:把所有SpanQuery查詢結果綜合起來,作為檢索結果。
    SpanNotQuery:從第一個SpanQuery查詢結果中,去掉第二個SpanQuery查詢結果,作為檢索結

    果。

    2, 多條件索引關系

    BooleanClause用于表示布爾查詢子句關系的類,包括:BooleanClause.Occur.MUST,

    BooleanClause.Occur.MUST_NOT,BooleanClause.Occur.SHOULD。有以下6種組合:
    1.MUST和MUST:取得連個查詢子句的交集。
    2.MUST和MUST_NOT:表示查詢結果中不能包含MUST_NOT所對應得查詢子句的檢索結果。
    3.MUST_NOT和MUST_NOT:無意義,檢索無結果。
    4.SHOULD與MUST、SHOULD與MUST_NOT:SHOULD與MUST連用時,無意義,結果為MUST子句的檢索

    結果。與MUST_NOT連用時,功能同MUST。
    5.SHOULD與SHOULD:表示“或”關系,最終檢索結果為所有檢索子句的并集。

    posted @ 2008-04-10 13:45 魯勝迪 閱讀(1799) | 評論 (0)編輯 收藏

    僅列出標題
    共12頁: First 上一頁 4 5 6 7 8 9 10 11 12 下一頁 
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導航

    統計

    常用鏈接

    留言簿(4)

    隨筆分類

    隨筆檔案

    文章分類

    新聞分類

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 美女羞羞视频免费网站| 亚洲综合一区二区国产精品| 男人天堂2018亚洲男人天堂| 精品熟女少妇av免费久久| 久久久久亚洲Av片无码v| 免费毛片a线观看| 亚洲福利秒拍一区二区| 最近中文字幕免费mv在线视频| 亚洲冬月枫中文字幕在线看| 国产h肉在线视频免费观看| 亚洲天堂男人影院| 国产美女无遮挡免费网站| 国产亚洲精品91| 一本色道久久综合亚洲精品高清| 中文在线观看免费网站| 久久综合日韩亚洲精品色| 亚洲一区二区免费视频| 亚洲国产欧美一区二区三区| 免费国产在线观看不卡| 亚洲免费日韩无码系列| 亚洲av中文无码乱人伦在线咪咕| 小草在线看片免费人成视久网| 亚洲一区二区三区国产精品无码| 岛国大片免费在线观看| 亚欧乱色国产精品免费视频| 亚洲成熟xxxxx电影| 在线免费观看一区二区三区| 免费播放国产性色生活片| 亚洲AV无码国产在丝袜线观看| 在线观看成人免费视频不卡| 极品美女一级毛片免费| 亚洲AV日韩精品久久久久久 | 免费福利网站在线观看| 亚洲AV无码一区二区三区牲色| 亚洲无码视频在线| 无遮免费网站在线入口| 九九综合VA免费看| 亚洲网红精品大秀在线观看| 四虎影视免费永久在线观看| 久久精品无码精品免费专区| 蜜桃传媒一区二区亚洲AV|