<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>longdick</title>
    <description></description>
    <link>http://longdick.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>[转] 川人从未负国，国人决不负川</title>
        <author>longdick</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://longdick.javaeye.com">longdick</a>&nbsp;
          链接：<a href="http://longdick.javaeye.com/blog/200024" style="color:red;">http://longdick.javaeye.com/blog/200024</a>&nbsp;
          发表时间: 2008年06月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>四川大地震后，流传着这样一句话，&ldquo;川人从未负国，国人决不负川&rdquo;。作为一个四川人，我在灾区采访时深深为此诗后半句感动，我所看到的一切，都印证了我们民族在危难时刻的众志成城。<br /><br />　　那么，&ldquo;川人从未负国&rdquo;说的又是什么呢？也有朋友问我为什么把MSN签名改为&ldquo;永历祥兴举省殉，国难向来蜀难先&rdquo;。上周我在报社的地震采访会上简略地解说了这句话背后的故事，在此把相关的史料转载于此。<br /><br />　　需要特别说明的是，历史上的侵略战争是当时游牧部落上层贵族为夺取土地、人口、金钱发动的非正义战争，使各族下层人民均经受了多年的死亡与痛苦，我们必须正视历史，予以谴责。抵抗一方在反对强大侵略者的过程中体现出来的精神，正是此次四川大地震中军民所体现出来的血脉传承之精魂，中华民族应该代代珍存。目前蒙、满、汉三兄弟民族已经融为统一的中华民族，我们应该分外珍惜通过流血、纷争、融合的历史而形成的新中国，而不应因为正视历史而曲解史实。<br /><br />　　南宋祥兴：举省殉国<br /><br />　　公元13世纪，蒙古骑兵扫荡欧亚大陆，中国未能幸免。南宋朝廷在联合蒙古灭掉世仇金国后，发现自己成为了蒙古贵族下一个征服的目标。当时蒙古上层贵族集团是一个武装抢劫集团，他们在欧亚大陆屠杀任何与之接壤的民族，从而获取大量奴隶人口和财富，花剌子模、黑衣大食等古国因为此次侵略战争而永远消失在地球表面。<br /><br />　　在经历了先秦至13世纪千余年的发展后，南宋时的四川省成为全中国最富庶、文明的省份之一。人们现在已经不知道，当时的四川出产全国最好的茶叶和丝织品，在全球最早出现纸质货币，有全国最多的书院，出过全国最好的文人，保存全国最多的古籍善本&hellip;&hellip;两宋时代文化的繁荣里，四川亚文化在其中占有极其重要的地位，这不仅因为四川向全国提供了占全国三分之一的税收，支持着国防和其他建设开资，而且四川以它的文化和人才成为全国的重要组成部分。<br /><br />　　失去四川，就失去了最重要的税收和兵员来源，南宋政府因此在四川组织了最激烈的抵抗。1242年，宋理宗派遣在两淮抗蒙战争中战绩颇著的余玠入蜀主政，以扭转四川的颓势，巩固上流。余玠在四川采取了一系列政治、经济和军事措施，其中最重要的是创建了山城防御体系。即在四川的主要江河沿岸及交通要道上，选择险峻的山隘筑城结寨，星罗棋布，互为声援，构成一完整的战略防御体系。<br /><br />　　在山城防御战中最著名的城市是合川钓鱼城，这座城市孤城独守36年，在南宋灭亡后还继续抵抗多年，并且击毙蒙古大汗蒙哥，扭转了欧亚战争格局。<br /><br />　　整个元朝统治四川七十五年的时间里，虽然元政府对四川战后经济的恢复作过努力，例如疏浚都江堰灌溉工程，鼓励垦荒屯田，然而毕竟因为四川人口太少，经济恢复的程度并不显著。而且，它不象清政府在明末清初动乱以后那样，大规模组织对四川的移民，以便加速恢复四川的经济。在元、明两代，四川的传统经济，如茶、丝，都已失去了她在元以前在全国的领先地位，降至清代，人们几乎忘记了四川曾经生产过优质的丝、茶产品。<br /><br />　　在文化方面，元王朝最多做的事，就是驻扎成都的元帅纽璘，因为本人热爱儒学，在成都一地帮助恢复了三所书院而已，后来政府却又宣布把书院纳入官办，这和宋王朝鼓励私人办书院和官办郡县学相辅相成适成鲜明对比。我们说，自从汉唐到两宋以来的四川亚文化的代表&mdash;&mdash;&ldquo;蜀学&rdquo;，在蒙古侵宋战争结束以后彻底衰落了，这是有根据的。<br /><br />　　四川军民通过大无畏的牺牲精神，彻底让蒙古贵族放弃了把耕地变为牧场这一可能让汉族亡国灭种的政策。蒙哥之后上台的忽必烈汗，是元代历史上的明君，他采取了许多在贵族集团强大压力下依然施行的缓和民族矛盾，促进民族融合的政策，比如大批任用汉族官吏，按照前朝典章制度治理社会等。<br /><br />　　正是在四川经历了长达半个世纪的战争后，蒙古上层贵族集团意识到，并不是所有民族都会轻易在屠刀下屈服，夺取政权后，只有不分族群地善待人民才有可能坐稳皇位。忽必烈的继任者们并未体察到他的用心，因此没有多长时间便在南方各族激烈的反抗中丢掉了江山并逐渐衰落。<br /><br />　　南明永历：举省殉国<br /><br />　　由于南宋末年经历的大屠杀，四川省在明初时依然只有一个省级行政单位，全省大部分国土已经恢复成为动物的乐园，其时有旅行者在从前的城池中看到虎豹成群结队出没。<br /><br />　　为了恢复人口，朱元璋大幅度提高湖广赋税，并用军队强迫百姓前往四川落户，第一次湖广填四川自此开始，我家的祖先便是在这次迁徙中进入四川的。<br /><br />　　经过明代200多年的恢复，四川人口有所恢复，但到崇祯时也不过区区310万而已，与南宋的1290万自然不可同日而语。然而，由于清军在四川反复追剿张献忠、李自成义军余部，这310万人口至康熙初年已经损失了90%以上，再度沦为元代的千里无人烟的状态。<br /><br />　　　　保路运动：成就辛亥革命<br /><br />　　1911年5月(宣统三年四月)，清政府将已经由民办的川汉铁路强行收归&ldquo;国有&rdquo;，随后又将筑路权出卖给英、法、德、美四国银行团，激起四川人民强烈反对。<br /><br />　　6月17日，川汉铁路股东在成都组织保路同志会，推立宪党人蒲殿俊、罗纶为正副会长，各府州县相继建立分会，入会者达数十万人。至8月下旬发展为罢市、罢课和抗粮抗捐的群众斗争。同盟会员龙鸣剑、王天杰等乘势联络会党，组织保路同志军。9月7日，四川总督赵尔丰诱捕保路同志会代表，封闭铁路公司，命军警开枪打死请愿群众数百人。次日下令解散各处保路同志会。民众奋起反抗，保路同志军在各县发动武装起义。9月25日，同盟会员吴玉章、王天杰宣布荣县独立，建立了辛亥革命时期第一个县级革命政权，进而在四川全省发展为反清大起义，成为武昌起义的前奏。11月27日，成都宣布独立，成立大汉四川军政府，清王朝在四川的统治彻底覆灭。<br /><br />　　一个事实是，清廷在镇压保路运动过程中将武汉守军悉数调往四川，这是武昌首义能够成功的关键因素。<br /><br />　　川军抗战：壮士一去不复还<br /><br />　　抗战全面爆发后，四川省主席刘湘为首的川军七个集团军，另有一军一师一旅共40余万人，先后开赴抗战前线浴血奋战，此后四川每年向前方输送青壮年军人，人数居全国之冠。<br /><br />　　"模范父亲"的安县王者成，送其自动请缨出征的儿子王建堂时场景催人泪下：他赠送给儿子的竟是一面"死"字旗！他在白布旗正中写了个大大的"死"字，旗子左方写道："国难当头，日寇狰狞。国家兴亡，匹夫有分。本欲服役，奈过年龄。幸吾有子，自觉请缨。赐旗一面，时刻随身。伤时拭血，死后裹身。勇往直前，勿忘本分！"<br /><br />　　曾任国民政府军政部长的何应钦曾写过《八年抗日之经过》一书，书中记载川军出川人数令人震撼：抗战8年中，四川(包括西康省及特种部队和军事学校征的10万余人)提供了近300万人的兵源充实前线部队，占全国同期实征壮丁1405万余人的五分之一还多！四川出川将士伤亡人数约为全国抗日军队的十分之二，即阵亡263991人，负伤356267人，失踪26025人，共计64万余人，居全国之冠。<br /><br />　　带病出征的四川军阀刘湘，在抗战前线吐血病发，于1938年1月20日在汉口去世。死前留下遗嘱：&ldquo;抗战到底，始终不渝，即敌军一日不退出国境，川军则一日誓不还乡！&rdquo;<br /><br />　　对于这段历史，李宗仁将军曾说：&ldquo;八年抗战，川军之功，殊不可没。刘湘在全国各大军阀中，抗日做的是最决绝的一个。<br /><br />　　1937年&ldquo;淞沪抗战&rdquo;爆发第二天，川军就请缨抗日，当年9月1日，川军从安顺场出发，历时41天到达上海前线，防守&ldquo;四行仓库&rdquo;等一线阵地，拉开了川军抗日第一战；<br /><br />　　1937年11月22日，川军开赴太湖阻击日军，20多名战士深入敌后，身绑手榴弹与鬼子同归于尽；<br /><br />　　台湾出版的《一寸山河一寸血》记录说：川军1937年初夏步行出川北上抗日(从秦岭出川)。很多军人只有两件单衣，一双草鞋。一路上无有任何补给，但经历了北方严寒的考验，不得以还抢了阎锡山的军库，以补充补给。当时国军主力都不愿意接纳军纪涣散，素有双枪将(土枪＋烟枪)之称的川军。最后李宗仁收留了川军。川军未及休整就投入了台儿庄战役,承担了正面阻击日寇的重大任务,其作战英勇另各部正规军刮目相看。川军也承受了巨大损失，有一个师几乎拼光。当时师长打电话给李宗仁，说给我们川军留一点种子吧。李宗仁当时知道对日军的包围已经快合陇，因而不同意。师长也坚决服从命令，最后全体官兵阵亡。<br /><br />　　八年抗战，回川者寥寥。在成都，每年清明市民都群起祭祀抗战川军，祭品大多是一碗汤圆。这里有一个传说：有年寒冬腊月沉沉深夜，有个衣衫单薄的穷军人走到城门洞边卖汤圆的小摊子前，看来是又冷又饿，埋头呼呼呼地只顾吃汤圆。眨眼间，穷当兵的却不见了！卖汤圆的小贩恍然大悟：当年出川抗战的川军苦啊，是那个赴国难牺牲的"无名英雄"从阴间来吃汤圆了！消息传开，百姓们都哭了："天冷了，他又冷又饿，莫让他在阴间受苦呀！"于是一家又一家，流泪端来一碗又一碗热气腾腾的汤圆，到铜像前祭奠。<br /><br />　　八年抗战岁月漫漫，整个中国的钱粮支撑，就主要靠&ldquo;陪都&rdquo;所在地的四川这个&ldquo;大后方&rdquo;来负担了。抗战最困难时期，估计四川负担了国家财政总支出的30%以上。以八年抗战总计，国家支出14640亿元(法币)，四川就负担了约4400亿元。四川出粮也最多，仅1941年至1945年，四川共征收稻谷8228.6万市石，占全国征收稻谷总量的38.75%、稻麦总量的31.63%。<br /><br />　　这么多粮食，是四川百姓勒紧裤腰带奉献出来的！1941年四川省田赋管理处长甘绩镛行经南、潼道上，在一处茅草房前歇脚休憩，问一个老农民：&ldquo;今年收成和生活情形咋样？&rdquo;老农回答说：&ldquo;老天爷不作美，我们经常以苕藤菜叶和杂粮充饥。&rdquo;甘绩镛又问：&ldquo;粮食不够，还给国家纳粮吗？&rdquo;老农民说：&ldquo;我应缴的粮食都缴了，左邻右舍都是这样的！&rdquo;甘绩镛问：&ldquo;你们自己都填不饱肚子，还有啥余粮缴公呢？&rdquo;老农慨然说：&ldquo;军队去前方打仗，没粮食就吃不饱，就是有条命也不能拼啊&hellip;&hellip;只要能打胜仗，赶走日本鬼子，能过太平日子，我们老百姓暂时吃苕藤树叶，也有想头，比起日本人来抢我们好多了！&rdquo;还有一个农妇，儿子出川抗战，她孤身一人无余粮交公，把陪伴自己的一只猫儿卖了买粮交公，说：&ldquo;我儿子爱国，我也要爱国啊！&rdquo;战时粮食奇缺，全川物价暴涨。成都1942年12月至1943年1月，一月之内米价上涨3倍以上，粮、糖、盐、火柴等，都曾限量供应。几千万四川普通民众都挣扎在饥寒线上。<br /><br />　　万般困苦艰难的情况下，四川百姓们仍加紧耕种、生产，支援前方。抗战军队的军火枪械，穿的军衣等，当时主要是靠待遇菲薄的四川工人日以继夜加班加点生产出来的。川江上赤裸上身的航运船工，吼着悲壮的川江号子、积极运输部队、军粮、难民和军需、民用物资&hellip;&hellip;<br /><br />　　到抗战中后期，国家财政困难万分，军费紧张，全川又掀起了献金高潮。1944年春，国民政府军委会副委员长冯玉祥将军到川中各地劝导节约献金，进一步推动了献金运动。这年1月17日，&ldquo;成都市各界民众献金救国大会&rdquo;在少城公园内行。从张群、余中英(市长)等官员，到市民、商人、教师、静环等川剧艺人&hellip;&hellip;无不踊跃捐献。最催人泪下的情景出现了：只见一长串衣不蔽体、瞎眼跛脚的乞丐，一个挽一个踉踉跄跄把乞讨来的全部铜元、镍币，叮叮当当放进&ldquo;救国献金柜&rdquo;里，然后蹒跚下台&hellip;&hellip;全场哭声顿起，争先恐后地掀起又一轮献金高潮！<br /><br />　　据国民党中央宣传部发表的不完全统计，抗战中四川各地献金总额为5亿多元。这些钱，是四川人民一滴一滴地挤出来的血！这笔巨款，有力地支持了抗战。<br /><br />　　1940年9月后，重庆正式定为中国战时的首都(陪都)，成为中国政治、经济、军事、文化的中心。日本人深知&ldquo;中国大后方&rdquo;四川的重要，对四川的轰炸前后持续了6年多时间，四川老百姓承受了巨大灾难。据统计，日本对四川的轰炸共有26000余人被炸伤，22500余人被炸死，财产损失难以统计&hellip;&hellip;<br /><br />　　对印、对越自卫反击战：几乎每个县都阵亡上百人<br /><br />　　在新中国建国后，我国经历了两次邻国发动的侵略战争，即对印、对越自卫反击战。作为与印度、越南接壤的西南地区中心城市，成都的军分区第一个承担了派兵作战的任务。小时候每到清明，我和同学都会在学校组织下去县里的烈士陵园扫墓，在碑文上，我看到了我们县大量在这两次作战中阵亡的烈士名单。据后来认识的一个越战老兵告诉我，在这两次战争中，四川几乎每个县都阵亡了上百人(当时重庆还未划出，四川约有220个县)。<br /><br />　　罗列少量殉国军人名单，以作纪念：<br /><br />　　麻栗坡英灵名单烈士姓名生前所在部队籍贯牺牲时间潘相安35206部队59分队四川安岳84年4月28日吾尔尔且35215部队73分队四川昭觉县81年5月22日吴伯祥35215部队73分队四川西昌81年5月22日黑哈旦35207部队59分队四川昭觉84年4月28日李光文35214部队四川西昌1982年2月谭孟年35207部队四川会理县84年4月28日杨正科35206部队四川会理县84年6月28日罗平 35206部队40分队四川成都84年7月21日江绪强35206部队四川德阳84年7月12日孙守华35205部队四川璜县84年5月19日；&hellip;&hellip;<br /><br />　　对印自卫反击战相文浩7971部队战士四川乐至62年11月牺牲鄢登勇7972部队战士四川简阳62年11月牺牲晋朝福7975部队战士四川简阳62年牺牲　吴洪良7971部队战士四川乐至62年11月牺牲　鄢家发7971部队战士四川简阳62年10月牺牲倪邦海7979部队副班长四川乐至62年11月牺牲刘祖积7971部队战士四川乐至62年10月牺牲王云超7979部队班长四川乐至62年10月牺牲　张信华7979部队副班长四川乐至62年10月牺牲王再清7979部队战士四川乐至62年11月牺牲熊兴民四川长县82年因公牺牲　杨相军36923部队战士四川宜宾82年2月牺牲　魏存良36923部队战士四川宜宾82年2月牺牲　阿加福36923部队战士四川什祁82年2月牺牲　&hellip;&hellip;<br /><br />　　&ldquo;川人从未负国&rdquo;，此言确实凿凿！</p>
          <br/>
          <span style="color:red;">
            <a href="http://longdick.javaeye.com/blog/200024#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 04 Jun 2008 11:06:22 +0800</pubDate>
        <link>http://longdick.javaeye.com/blog/200024</link>
        <guid>http://longdick.javaeye.com/blog/200024</guid>
      </item>
      <item>
        <title>DWR使用要点 </title>
        <author>longdick</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://longdick.javaeye.com">longdick</a>&nbsp;
          链接：<a href="http://longdick.javaeye.com/blog/193905" style="color:red;">http://longdick.javaeye.com/blog/193905</a>&nbsp;
          发表时间: 2008年05月17日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>想在JAVA WEB项目中应用AJAX？当然有不少解决方案，其中应用DWR是个不错的选择，使用起来省时又省力。</p>
<p>&nbsp;</p>
<p>DWR（Direct Web Remoting）是一个开源的类库,可以帮助开发人员开发包含AJAX技术的网站.它可以允许在浏览器里的代码使用运行在WEB服务器上的JAVA函数,就像它就在浏览器里一样.</p>
<p>&nbsp;</p>
<p>DWR不认为浏览器/WEB服务器协议是重要的,而更乐于保证编程界面的简单自然.对此最大的挑战就是把AJAX的异步特性和正常JAVA方法调用的同步特性相结合.在异步模式下,结果数据在开始调用之后的一段时间之后才可以被异步访问获取到.也就是说浏览者可以在页面上远程调用服务器端的方法而不用担心提交请求的过程会阻塞浏览的进程，他们完全可以在等待响应的同时在页面上做其他的操作。从浏览者的角度看，在操作的过程中基本上感觉不到响应时间，这对提升浏览者的浏览体验非常有好处。</p>
<p>&nbsp;</p>
<p>DWR允许WEB开发人员传递一个回调函数,来异步处理 Java函数调用过程.</p>
<p>类似如下定义：</p>
<p>在服务端的java方法定义: &nbsp;DemoService.doSomething(String name,String addr){return name+addr;}</p>
<p>在浏览器Javascript中的调用:&nbsp;&nbsp;DemoService.doSomething(name,addr,callback)</p>
<p>&nbsp;</p>
<p>&nbsp;callback就是回调函数，开发人员可以用这个回调函数在取得doSomething方法的返回值时做一些处理，在Javascript里可以这样定义：</p>
<p>var callback=function(data){};参数data即调用DemoService类doSomething方法的返回值，当DWR接收到这个返回值时，便会调用这个回调函数，并把doSomething方法返回值作为参数传给回调函数，后台没有返回之前是不会调用的。</p>
<p>&nbsp;</p>
<pre name="code" class="js">var resultValue=&quot;firstValue&quot;;

var callback=function(data){
resultValue=data;
}

function doRemoteService(name,addr){
DemoService.doSomething(name,addr,callback);
alert(resultValue);
}</pre>
<p>&nbsp;</p>
<p>看上面一段js代码，很简单是吗，你觉得调用doRemoteService方法的时候会弹出什么值呢？由于DWR默认是异步调用远程函数的，调用callback的时机也许很快，但是也有可能需要过一段时间，在浏览器端调用js方法却是微秒级别的，所以，在回调函数被调用之前，alert已经被调用了。</p>
<p>&nbsp;</p>
<p>很多人在使用DWR的时候会遇到这个问题，如果想要拿到期望的值，必须关闭DWR的异步特性。可以如下修改：</p>
<p>&nbsp;</p>
<pre name="code" class="js">function doRemoteService(name,addr){
DWREngine.setAsync(false);
DemoService.doSomething(name,addr,callback);
DWREngine.setAsync(true);
alert(resultValue);
}</pre>
<p>&nbsp;</p>
<p>DWREngine.setAsync()可以设定DWR调用方式为异步还是同步。在一些不希望异步特性的场合会用到。</p>
<p>&nbsp;</p>
<p>在WEB应用中会不可避免的用到request，session，context等的Http对象，在DWR应用中要如何调用呢，</p>
<p>可以在服务端的java方法定义: &nbsp;</p>
<p>DemoService.doSomething(String name,String addr,HttpServletRequest request){return name+addr;}</p>
<p>在浏览器Javascript中的调用方式不用改变，DWR会自动传入HttpServletRequest 参数:&nbsp;</p>
<p>&nbsp;DemoService.doSomething(name,addr,callback)</p>
<p>这样我们就可以直接在Java方法里调用从DWR传过来的request对象，HttpServletRequest,HttpServletResponse,HttpSession,ServletContext等对象使用方式类似。</p>
<p>&nbsp;</p>
<p>当然还可以直接在java方法里调用DWR的API：</p>
<p>&nbsp;</p>
<pre name="code" class="java">WebContext ctx = WebContextFactory.get();
ctx.getSession();
ctx.getHttpServletRequest();</pre>
<p>&nbsp;</p>
<p>注1：以上所有代码在JDK1.4.2 ，DWR1.1.1，webspere6.0环境下测试通过。</p>
<p>&nbsp;</p>
<p>注2：webspere6.0 不支持JDK5.0以后的版本，DWR 2.x 包含了 Java5 支持的内容。在应用时可能出现不能正常运行的情况，现在在webspere6.0上还是使用dwr1.X版本。</p>
<p>&nbsp;</p>
<p>注3：DWR现在最新版本是2.0.3， 3.0版本正在开发中。</p>
<p>&nbsp;</p>
<p>参考资料：官方网站<a href="http://getahead.org/dwr" title="http://getahead.org/dwr">http://getahead.org/dwr</a></p>
          <br/>
          <span style="color:red;">
            <a href="http://longdick.javaeye.com/blog/193905#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 17 May 2008 16:19:54 +0800</pubDate>
        <link>http://longdick.javaeye.com/blog/193905</link>
        <guid>http://longdick.javaeye.com/blog/193905</guid>
      </item>
      <item>
        <title>Hibernate 中 formula的简单应用</title>
        <author>longdick</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://longdick.javaeye.com">longdick</a>&nbsp;
          链接：<a href="http://longdick.javaeye.com/blog/184600" style="color:red;">http://longdick.javaeye.com/blog/184600</a>&nbsp;
          发表时间: 2008年04月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>在一个项目的某一个查询场景中，TEACHER表是主表，STUDENT表是TEACHER的子表，两者是以一对多的方式关联。业务逻辑需要查询多条TEACHER表的数据，并且在查询出每条A表数据的同时还需要将对应STUDENT表的行数取出来。我们当然可以利用Hibernate先将每条TEACHER数据load进来以后再以TEACHER.getStudents().size()这种方式取得对应的行数，但是代码会显得很繁琐并且增加了许多需要执行的SQL语句，有没有什么替代的方法呢？</p>
<p>&nbsp;</p>
<p>我们可以使用Hiberante的formula。</p>
<p>&nbsp;</p>
<p>为了解决前面提到的问题，我们只需要在TEACHER 的orm配置文件里加上这样一个property，定义其formula属性如下：</p>
<p>&nbsp;</p>
<pre name="code" class="xml">...
&lt;property name=&quot;rowCount&quot; formula=&quot;(select count(*) from STUDENT a where a.ID=teacherId)&quot; 
type=&quot;java.lang.String&quot; /&gt;
...
</pre>
<p>&nbsp;</p>
<p>&nbsp;通过这种方式我们就可以在取得每一个TEACHER持久化对象的时候就方便的得到了需要的统计信息，可以大幅度的提高我们的开发效率。注意这里不单单可以用来统计记数，还可以用于sum，avg等其他统计。</p>
<p>&nbsp;</p>
<p>在Hibernate 3.x之前，formula属性只能够出现在property元素中。现在仍然可以这样做，但是Hibernate
3.x提供了一个formula属性或元素（两者在formula的用法方面实质上是等效的），可以在许多元素中使用，包括discriminator、
many-to-one、one-to-one、element、many-to-many、map-key、map-key-many-to-many
和property。这样就大大提高了对象关系映射的灵活性，从而支持对复杂数据
模型的更为细粒度的解释。</p>
<p>&nbsp;</p>
<p>从3.x开始，Hibernate 使用formula、filter、subselect等提高映射灵活性，提供细粒度的解释特性，从而将其推进到一个新的级别。</p>
<p>&nbsp;</p>
<p>需要知道更多的有关formula使用方法的，可以参考 <a href="../../../blog/184591" title="Hibernate3 中的 formula" target="_blank">这一篇</a>
</p>
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://longdick.javaeye.com/blog/184600#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 20 Apr 2008 16:34:13 +0800</pubDate>
        <link>http://longdick.javaeye.com/blog/184600</link>
        <guid>http://longdick.javaeye.com/blog/184600</guid>
      </item>
      <item>
        <title>[转]Hibernate 3中的formula</title>
        <author>longdick</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://longdick.javaeye.com">longdick</a>&nbsp;
          链接：<a href="http://longdick.javaeye.com/blog/184591" style="color:red;">http://longdick.javaeye.com/blog/184591</a>&nbsp;
          发表时间: 2008年04月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>时间：2006-01-09<br />
作者：<a href="http://dev2dev.bea.com.cn/author/436.html">Dai Yifan</a>
</p>
<p>&nbsp;</p>
<p><a href="http://www.hibernate.org/" target="_blank">Hibernate</a>
和<a href="http://www.springframework.org/" target="_blank">Spring</a>
是两个杰出的开源框架，它们在越来越多的J2EE应用中得到采用。尽管它们致力于解决的问题有很大区别，它们却都有一个重要特性：<a href="http://martinfowler.com/articles/injection.html" target="_blank">依赖注入</a>
。Spring有助于在将对象返回给客户端之前整理出对象之间的依赖关系，从而大大减少客户端的编码。而Hibernate则擅长于在将整个<a href="http://www.onjava.com/pub/a/onjava/2005/08/03/hibernate.html" target="_blank">对象模型</a>
返回给客户端之前整理出数据模型所表现的依赖关系。当直接使用JDBC将数据模型映射为对象模型时，我们通常需要编写大量的代码以构建对象模型。而Hibernate消除了其中的大部分编码工作。
</p>
<p>　　Hibernate
2.x提供了基本的表格到对象的映射、常见的关联映射（包括一对一、一对多和多对多关联）、多态映射等等。Hibernate
3.x则通过使用formula、filter、subselect等提高映射灵活性，提供细粒度的解释特性，从而将其推进到一个新的级别。</p>
<p>　　在本文中，我们将展示有助于模型转换的各种formula特性。在Hibernate
3.x之前，formula属性只能够出现在property元素中。现在仍然可以这样做，但是Hibernate
3.x提供了一个formula属性或元素（两者在formula的用法方面实质上是等效的），可以在许多元素中使用，包括discriminator、
many-to-one、one-to-one、element、many-to-many、map-key、map-key-many-to-many
和property。这样就大大提高了对象关系映射的灵活性，从而支持对复杂<a href="http://www.onjava.com/pub/a/onjava/2005/08/03/hibernate.html" target="_blank">数据</a>
模型的更为细粒度的解释。</p>
<p align="left">　　基本上，有两种情况必须使用formula：</p>
<ul>
<li><strong>需要formula的计算结果时</strong>
。与元素discriminator、element、map-key、map-key-many-to-many和property一起使用formula属于这类情况。</li>
<li><strong>为了连接的目的需要使用formula</strong>
时。与元素many-to-one、one-to-one和many-to-many一起使用formula属于这类情况。</li>
</ul>
<p>
<strong>第一类：从formula获取计算结果</strong>
<strong>Discriminator（识别器）</strong>
<br />
　　在现实数据模式中，经常出现使用一个表来描述另一个表的情况。在对象关系映射中，Formula有助于提供灵活的多态性。
</p>
<p>　　在图1展示的例子中，有两个表：Product和ProductRelease。每个产品记录有一个ProductReleaseID来引用它对应的产品版本记录，包括产品版本名称、类型、版本日期等。</p>
<p align="center"><img src="http://dev2dev.bea.com.cn/images/image060109001.jpg" height="338" alt="Product and Product Release Data Model" width="344" />
<br />
图1. 产品和产品版本<a href="http://www.onjava.com/pub/a/onjava/2005/08/03/hibernate.html" target="_blank">数据模型</a>
</p>
<p>　　在ProductRelease表中有一个值得注意的属性是SubProductAllowable，它的值可以是0或1。值为1意味着允许该
产品版本中的任何产品有子产品，而值为0则意味着不允许有子产品。例如，有些产品由多个子产品组成，而有些产品只有该产品本身。</p>
<p>　　图2展示了一个对该数据模型解释而成的对象模型。Nested接口定义了getSubProducts和setSubProducts方法。
NestedProduct类扩展了基类Product并实现了Nested接口。一个产品数据记录应该是Product还是NestedProduct
取决于相应产品版本记录的SubProductAllowable值。</p>
<p align="center"><img src="http://dev2dev.bea.com.cn/images/image060109002.jpg" height="333" alt="Product and Product Release Object Domain Model" width="375" />
<br />
图2. 产品和产品版本对象的域模型</p>
<p>　　为了完成这个模型转换，我们使用了Hibernate 3.x映射，如下：</p>
<pre class="code">&lt;hibernate-mapping&gt;  &lt;class name=&quot;Product&quot;         discriminator-value=&quot;0&quot;  lazy=&quot;false&quot;&gt;    &lt;id name=&quot;id&quot; type=&quot;long&quot;/&gt;           &lt;discriminator         formula=&quot;(select pr.SubProductAllowable                 from ProductRelease pr                 where pr.productReleaseID=                        productReleaseID)&quot;        type=&quot;integer&quot; /&gt;    &lt;subclass  name=&quot;NestedProduct&quot;          discriminator-value=&quot;1&quot;/&gt;  &lt;/class&gt;&lt;/hibernate-mapping&gt;</pre>
<p>　　如果formula表达式计算结果为0，也就是不支持子产品，则对象将属于Product类。如果结果是1，对象将是一个
NestedProduct。在表1和表2中，对Product表中的第一个记录(ProductID=10000001)来说，初始化的类将是
NestedProduct，因为它引用一个SubProductAllowable=1的ProductRelease记录。对Product表中的第
二个记录(ProductID=20000001)来说，初始化的类将是Product，因为它引用一个SubProductAllowable=0的
ProductRelease记录。</p>
<table cellspacing="1" border="0" align="center" bgcolor="#000000" cellpadding="4">
<tbody>
<tr bgcolor="#ffffff">
<td width="10%">S/N</td>
<td width="35%">ProductReleaseID</td>
<td width="35%">SubProductAllowable</td>
<td width="20%">...</td>
</tr>
<tr bgcolor="#ffffff">
<td>1</td>
<td>11</td>
<td>1</td>
<td>i </td>
</tr>
<tr bgcolor="#ffffff">
<td>2</td>
<td>601</td>
<td>0</td>
<td>i</td>
</tr>
</tbody>
</table>
<div>. ProductRelease表中的记录</div>
<p>&nbsp;</p>
<table cellspacing="1" border="0" align="center" bgcolor="#000000" cellpadding="4">
<tbody>
<tr bgcolor="#ffffff">
<td width="10%">S/N</td>
<td width="35%">ProductID</td>
<td width="35%">ProductReleaseID</td>
<td width="20%">...</td>
</tr>
<tr bgcolor="#ffffff">
<td>1</td>
<td>10000001</td>
<td>11</td>
<td>i</td>
</tr>
<tr bgcolor="#ffffff">
<td>2</td>
<td>20000001</td>
<td>601</td>
<td>...</td>
</tr>
</tbody>
</table>
<div>表 2. Product表中的记录</div>
<p>
<strong>Property</strong>
<br />
　　Property元素中的formula允许对象属性包含导出值，比如sum、average、max等的结果。如：
</p>
<p>&lt;property name=&quot;averagePrice&quot; formula=&quot;(select avg(pc.price) from
PriceCatalogue pc, SelectedItems si where
si.priceRefID=pc.priceID)&quot;/&gt;</p>
<p>　　此外，formula还可以基于当前记录的特定属性值从另一个表检索值。例如：</p>
<p>&lt;property name=&quot;currencyName&quot; formula=&quot;(select cur.name from currency cur where cur.id= currencyID)&quot;/&gt;</p>
<p>　　它从currency表检索货币名称。如您所见，这些直接的映射可以消除大量的转换编码。</p>
<p>
<strong>map-key<br />
　　</strong>
formula允许map-key取任何可能的值。在下面的例子中（图3）,我们希望Role_roleID成为<a href="http://www.onjava.com/pub/a/onjava/2005/08/03/hibernate.html?page=2" target="_blank">对象模型的map-key</a>
（图4）。
</p>
<p align="center"><img src="http://dev2dev.bea.com.cn/images/image060109003.jpg" height="417" alt="User Role Data Schema" width="316" />
<br />
图3. 用户角色<a href="http://www.onjava.com/pub/a/onjava/2005/08/03/hibernate.html?page=2" target="_blank">数据</a>
模式</p>
<p align="center"><img src="http://dev2dev.bea.com.cn/images/image060109004.jpg" height="180" alt="User Role Object Model" width="431" />
<br />
图4. 用户角色对象模型</p>
<p>　　在上面的数据<a href="http://www.onjava.com/pub/a/onjava/2005/08/03/hibernate.html?page=2" target="_blank">模式中</a>
，User和Role被通过一个称为User_has_Role的多对多的关系表连接起来。为了获取一个User以及分配给它的所有角色，我们使用下面的映射：</p>
<pre class="code">&lt;hibernate-mapping&gt;  &lt;class name=&quot;User&quot;&gt;    &lt;id name=&quot;userID&quot;/&gt;    &lt;map name=&quot;roles&quot;          table=&quot;UserRole&quot;/&gt;      &lt;key column=&quot;User_userID&quot;/&gt;      &lt;map-key         formula=&quot;Role_RoleID&quot;         type=&quot;string&quot;/&gt;      &lt;many-to-many         column=&quot;Role_RoleID&quot;        class=&quot;Role&quot;/&gt;    &lt;/map&gt;  &lt;/class&gt;  &lt;class name=&quot;Role&quot;&gt;    &lt;id name=&quot;roleID&quot;/&gt;  &lt;/class&gt;&lt;/hibernate-mapping&gt;</pre>
<p>
　　Role_RoleID用作many-to-many元素的连接列值。然而，Hibernate不允许map-key和many-to-many的
column属性同时使用Role_RoleID。但是使用一个formula,Role_RoleID还是可以用于map-key。
</p>
<p>　　Formula和map-key-many-to-many的用法与map-key类似。然而，map-key-many-to-many通常用于三重关联，其中map键是被引用的对象自身，而不是一个被引用的属性。</p>
<p>　　然而，有些地方不支持formula。有些数据库（如Oracle 7）不支持嵌入的select语句（即，嵌入一个<a href="http://www.onjava.com/pub/a/onjava/2005/08/03/hibernate.html?page=3" target="_blank">SQL</a>
语句的select部分中的select<a href="http://www.onjava.com/pub/a/onjava/2005/08/03/hibernate.html?page=3" target="_blank">SQL</a>
)，也不支持用于计算结果的formula。因此，需要首先检查是否支持嵌入式的select<a href="http://www.onjava.com/pub/a/onjava/2005/08/03/hibernate.html?page=3" target="_blank">SQL语句。</a>
</p>
<p>　　因为由Hibernate映射生成的SQL将formula表达式作为其select目标的一部分，所以对所使用的数据库的非标准语言将有助于充分使用formula，尽管这可能会降低代码的可移植性。</p>
<p>
<strong>第二类：将formula用于连接</strong>
<strong>many-to-one<br />
　　</strong>
现实世界数据模型中的另一个常见场景是私有关系映射，它是指除基本的一对一、一对多和多对多关系之
外的映射。formula是针对这种私有关系管理所提供的元素之一。图5展示了一个例子，其中一个公司可以有多个联系人，但是他们之中只能有一个是默认的
联系人。一个公司有多个联系人是典型的一对多关系。但是，为了标识默认联系人，ContactPerson表使用了一个defaultFlag属性（1为
是，0为否）。
</p>
<p align="center"><img src="http://dev2dev.bea.com.cn/images/image060109005.jpg" height="327" alt="" width="272" />
<br />
图5. 用户角色数据模式</p>
<p align="center"><img src="http://dev2dev.bea.com.cn/images/image060109006.jpg" height="121" alt="" width="281" />
<br />
图6. 用户角色对象模型</p>
<p>　　为了将默认联系人关系解释为对象模型（图6），我们使用下面的映射：</p>
<pre class="code">&lt;hibernate-mapping&gt;  &lt;class name=&quot;Company&quot; table=&quot;Company&quot;&gt;    &lt;id name=&quot;id&quot; /&gt;    &lt;many-to-one       name=&quot;defaultContactPerson&quot;       property-ref=&quot;defaultContactPerson&quot;&gt;        &lt;column name=&quot;id&quot;/&gt;        &lt;formula&gt;1&lt;/formula&gt;        &lt;/many-to-one&gt;  &lt;/class&gt;  &lt;class name=&quot;Person&quot; &gt;    &lt;id name=&quot;id&quot; /&gt;    &lt;properties name=&quot;defaultContactPerson&quot;&gt;        &lt;property name=&quot;companyID&quot; /&gt;        &lt;property name=&quot;defaultFlag&quot; /&gt;    &lt;/properties&gt;  &lt;/class&gt;&lt;/hibernate-mapping&gt;</pre>
<p>　　我们将companyID和defaultFlag聚合到一个名为defaultContactPerson的properties元素中，形
成Person表的一个独有的键。将Company类中的many-to-one元素与Person类中的
defaultContactPersonproperties元素连接。产成的SQL将类似于：</p>
<p>select c.id, p.id from Company c, Person p where p.companyID=c.id and p.defaultFlag=1</p>
<p><strong>one-to-one</strong>
<br />
　　在Hibernate中，one-to-one主要用于两个表<a href="http://www.onjava.com/pub/a/onjava/2005/08/03/hibernate.html?page=4" target="_blank">共用相同的主键</a>
。而对于外键关联，通常使用many-to-one。但是，使用formula，one-to-one可以通过外键连接多个表。上面的many-to-one例子可以使用one-to-one映射为：</p>
<pre class="code">&lt;hibernate-mapping&gt;  &lt;class name=&quot;Company&quot; table=&quot;Company&quot; &gt;    &lt;id name=&quot;id&quot; /&gt;    &lt;one-to-one name=&quot;defaultContactPerson&quot;         property-ref=&quot;defaultContactPerson&quot; &gt;    &lt;formula&gt;id&lt;/formula&gt;    &lt;formula&gt;1&lt;/formula&gt;    &lt;/many-to-one&gt;  &lt;/class&gt;  &lt;class name=&quot;Person&quot; &gt;    &lt;id name=&quot;id&quot; /&gt;    &lt;properties name=&quot;defaultContactPerson&quot;&gt;      &lt;property name=&quot;companyID&quot; /&gt;      &lt;property name=&quot;defaultFlag&quot; /&gt;    &lt;/properties&gt;   &lt;/class&gt;&lt;/hibernate-mapping&gt;</pre>
<p>
  <strong>其他：many-to-many</strong>
  <br />
　　formula可以与many-to-many元素一起用于从关系表到实体表的特殊连接，尽管通常不需要这样做。</p>
<p><strong>结束语<br />
</strong>
　　本文中的例子展示了大部分的formula使用场景。当需要formula的计算值时，formula表达式将出现在产生的<a href="http://www.onjava.com/pub/a/onjava/2005/08/03/hibernate.html?page=4" target="_blank">SQL语句</a>
的select部分。而当formula用于连接时，它出现在产生的<a href="http://www.onjava.com/pub/a/onjava/2005/08/03/hibernate.html?page=4" target="_blank">SQL</a>
语句的where部分。此外，formula表达式可以使用任意的SQL非标准语言，只要目标数据库支持。因此，formula有助于无需编码地实现从数据模型到对象模型的细粒度映射。</p>
          <br/>
          <span style="color:red;">
            <a href="http://longdick.javaeye.com/blog/184591#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 20 Apr 2008 15:33:41 +0800</pubDate>
        <link>http://longdick.javaeye.com/blog/184591</link>
        <guid>http://longdick.javaeye.com/blog/184591</guid>
      </item>
      <item>
        <title>[转]Lucene-2.0学习文档</title>
        <author>longdick</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://longdick.javaeye.com">longdick</a>&nbsp;
          链接：<a href="http://longdick.javaeye.com/blog/170222" style="color:red;">http://longdick.javaeye.com/blog/170222</a>&nbsp;
          发表时间: 2008年03月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p class="MsoNormal" style="margin: 0cm -88.6pt 0pt 3.6pt; text-indent: -3.6pt"><span style="font-size: small"><span style="font-size: 14pt"><span style="font-size: small"><span style="font-size: 14pt">[转]Lucene-2.0学习文档</span></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm -88.6pt 0pt 3.6pt; text-indent: -3.6pt"><span style="font-size: small"><span style="font-size: 14pt">作者：Javafish(likunkun)</span></span></p>
<p class="MsoNormal" style="margin: 0cm -88.6pt 0pt 3.6pt; text-indent: -3.6pt"><span style="font-size: small"><span style="font-size: 14pt">Email:javafish@sunxin.org<br />
</span></span></p>
<p class="MsoNormal" style="margin: 0cm -88.6pt 0pt 3.6pt; text-indent: -3.6pt">&nbsp;</p>
<span style="font-size: small"><span style="font-size: 14pt">
<p><span style="font-size: small; font-family: Arial">Lucene是apache组织的一个用java实现全文搜索引擎的开源项目。</span></p>
<p><span style="font-size: small; font-family: Arial">其功能非常的强大，api也很简单。总得来说用Lucene来进行建立</span></p>
<p><span style="font-size: small; font-family: Arial">和搜索和操作数据库是差不多的(有点像)，Document可以看作是</span></p>
<p><span style="font-size: small; font-family: Arial">数据库的一行记录，Field可以看作是数据库的字段。用lucene实</span></p>
<p><span style="font-family: Arial"><span style="font-size: small">现搜索引擎就像用JDBC实现连接数据库一样简单。</span><br />
</span></p>
</span></span>
<p class="MsoNormal" style="margin: 0cm -88.6pt 0pt 3.6pt; text-indent: -3.6pt">&nbsp;</p>
<p class="MsoNormal" style="margin: 0cm -88.6pt 0pt 3.6pt; text-indent: -3.6pt">&nbsp;</p>
<p class="MsoNormal" style="margin: 0cm -88.6pt 0pt 4.8pt; text-indent: -4.8pt"><span>Lucene2.0，它与以前广泛应用和介绍的Lucene 1.4.3并不兼容。</span></p>
<p class="MsoNormal" style="margin: 0cm -88.6pt 0pt 4.8pt; text-indent: -4.8pt">&nbsp;</p>
<p class="MsoNormal" style="margin: 0cm -88.6pt 0pt 4.8pt; text-indent: -4.8pt"><span>Lucene2.0的下载地址是<a href="http://apache.justdn.org/lucene/java/">http://apache.justdn.org/lucene/java/</a></span></p>
<p class="MsoNormal" style="margin: 0cm -88.6pt 0pt 4.8pt; text-indent: -4.8pt">&nbsp;</p>
<p class="MsoNormal" style="margin: 0cm -88.6pt 0pt 3.55pt; text-indent: -3.55pt"><span style="font-family: 宋体">大家先看一个例子，通过这个例子来对</span><span>lucene</span><span style="font-family: 宋体">的一个大概的认识。</span></p>
<p class="MsoNormal" style="margin: 0cm -88.6pt 0pt 3.55pt; text-indent: -3.55pt"><span style="font-family: 宋体">一个</span><span>Junit</span><span style="font-family: 宋体">测试用例：</span><span>(</span><span style="font-family: 宋体">为了让代码清晰好看，我们将异常都抛出</span><span>)</span></p>
<p class="MsoNormal" style="margin: 0cm -88.6pt 0pt 3.55pt; text-indent: -3.55pt"><span>a)<span>&nbsp;&nbsp;&nbsp; </span></span><strong><span style="font-family: 宋体">这是一个建立文件索引的例子</span></strong></p><pre name="code" class="java">public void testIndexHello() throws IOException

    {

        Date date1 = new Date(); 

        //可以说是创建一个新的写入工具

        //第一个参数是要索引建立在哪个目录里

        //第二个参数是新建一个文本分析器,这里用的是标准的大家也可以自己写一个

        //第三个参数如果是true，在建立索引之前先将c:\\index目录清空。

        IndexWriter writer = new IndexWriter(&quot;c:\\index&quot;,new StandardAnalyzer(),true);

       

//      这个是数据源的文件夹

        File file = new File(&quot;c:\\file&quot;);

        /**

         * 例子主要是将C:\\file目录下的文件的内容进行建立索引，将文件路径作为搜索内容的附属.

         */

       

        if(file.isDirectory())

        {

            String[] fileList = file.list();

            for (int i = 0; i &lt; fileList.length; i++)

            {

//              建立一个新的文档,它可以看作是数据库的一行记录

                Document doc = new Document();

                File f = new File(file,

                        fileList[i]);

                Reader reader = new BufferedReader(new FileReader(f));

                doc.add(new Field(&quot;file&quot;,reader));//为doument添加field

                doc.add(new Field(&quot;path&quot;,f.getAbsolutePath(),Field.Store.YES,Field.Index.NO));

                writer.addDocument(doc);

            }

           

        }

        writer.close();//这一步是必须的，只有这样数据才会被写入索引的目录里

        Date date2 = new Date();

        System.out.println(&quot;用时&quot;+(date2.getTime()-date1.getTime())+&quot;毫秒&quot;);

}
</pre>&nbsp;<p class="MsoNormal" align="left" style="text-align: left">&nbsp;</p>
<p class="MsoNormal" align="left" style="text-align: left"><span style="font-size: 10pt; font-family: 宋体; color: black">注意：因为建立索引本来就是费时，所以说最后输出的用时会比较长，请不要奇怪。</span></p>
<p class="MsoNormal" align="left" style="margin: 0cm -88.6pt 0pt 3.4pt; text-indent: -3.4pt; text-align: left"><span style="font-size: 10pt; font-family: 宋体; color: black">b)</span><span style="font-size: 10pt; font-family: 宋体; color: black">一个通过索引来全文检索的例子</span></p><pre name="code" class="java">public void HelloSearch() throws IOException, ParseException

    {

        IndexSearcher indexSearcher = new IndexSearcher(&quot;c:\\index&quot;);//和上面的IndexWriter一样是一个工具

        QueryParser queryParser = new QueryParser(&quot;file&quot;,//这是一个分词器

                new StandardAnalyzer());

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        Query query = queryParser.parse(br.readLine());//这个地方Query是抽象类大家也注意一下，下面会讲到的

        Hits hits = indexSearcher.search(query);

        Document doc = null;

        System.out.print(&quot;正搜索................&quot;);

        for (int i = 0; i &lt; hits.length(); i++)

        {

            doc = hits.doc(i);

            System.out.println(&quot;内容是：&quot;+doc.get(&quot;file&quot;));//注意这里输出的是什么

            System.out.println(&quot;文件的路径是：&quot; + doc.get(&quot;path&quot;));

        }

    }</pre>&nbsp;<p class="MsoNormal" align="left" style="text-align: left">&nbsp;</p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-size: 10pt; font-family: 宋体; color: black">通过上面的两个例子应该可以看出<span>Lucene</span>还是比较简单的。</span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-size: 10pt; font-family: 宋体; color: black">运行一下上面的两个例子，大家可能会说怎么<span>doc.get(</span></span><span style="font-size: 10pt; color: black">&ldquo;</span><span style="font-size: 10pt; font-family: 宋体; color: black">file</span><span style="font-size: 10pt; color: black">&rdquo;</span><span style="font-size: 10pt; font-family: 宋体; color: black">);</span><span style="font-size: 10pt; font-family: 宋体; color: black">返回的是空呢<span>,</span>我们马上会讲到。</span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-size: 16pt; font-family: 宋体; color: black">下面讲一下索引的建立</span></strong></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">其实从上面的例子就可以看出建立索引就用到<span>Document,IndexWriter,Field</span>。</span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">最简单的步骤就是：</span></p>
<p class="MsoNormal" align="left" style="margin: 0cm -88.6pt 0pt 21pt; text-align: left"><span style="font-family: 宋体; color: black">首先分别<span>new </span>一个<span>Document</span>，<span>IndexWriter,Field</span></span></p>
<p class="MsoNormal" align="left" style="margin: 0cm -88.6pt 0pt 21pt; text-align: left"><span style="font-family: 宋体; color: black">然后用<span>Doument.add()</span>方法加入<span>Field,</span></span></p>
<p class="MsoNormal" align="left" style="margin: 0cm -88.6pt 0pt 21pt; text-align: left"><span>其次用IndexWrtier.addDocument()方法加入Document。</span></p>
<p class="MsoNormal" align="left" style="margin: 0cm -88.6pt 0pt 21pt; text-align: left"><span style="font-family: 宋体; color: black">最后调用一下<span>IndexWriter.close()</span>方法关闭输入索引，这一步非常的重要只有调用这个方法</span></p><p class="MsoNormal" align="left" style="margin: 0cm -88.6pt 0pt 21pt; text-align: left"><span style="font-family: 宋体; color: black">索引才会被写入索引的目录里，而这是被很多初学的人所忽略的。</span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">Document</span><span style="font-family: 宋体; color: black">没有什么好介绍的，把它的作用看成数据库中的一行记录就行。</span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">Field</span><span style="font-family: 宋体; color: black">是一个比较重要的也是比较复杂的：</span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">看一下它的构造函数有<span>5</span>个：</span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-size: 12pt"><a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.html#Field%28java.lang.String,%20byte%5B%5D,%20org.apache.lucene.document.Field.Store%29"><span style="font-size: 10.5pt">Field</span></a></span></strong><span style="font-size: 12pt">(<a href="http://java.sun.com/j2se/1.4/docs/api/java/lang/String.html" title="class or interface in java.lang"><span style="font-size: 10.5pt">String</span></a>&nbsp;name, byte[]&nbsp;value, <a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Store.html" title="class in org.apache.lucene.document"><span style="font-size: 10.5pt">Field.Store</span></a>&nbsp;store)</span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-size: 12pt"><a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.html#Field%28java.lang.String,%20java.io.Reader%29"><span style="font-size: 10.5pt">Field</span></a></span></strong><span style="font-size: 12pt">(<a href="http://java.sun.com/j2se/1.4/docs/api/java/lang/String.html" title="class or interface in java.lang"><span style="font-size: 10.5pt">String</span></a>&nbsp;name, <a href="http://java.sun.com/j2se/1.4/docs/api/java/io/Reader.html" title="class or interface in java.io"><span style="font-size: 10.5pt">Reader</span></a>&nbsp;reader)</span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-size: 12pt"><a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.html#Field%28java.lang.String,%20java.io.Reader,%20org.apache.lucene.document.Field.TermVector%29"><span style="font-size: 10.5pt">Field</span></a></span></strong><span style="font-size: 12pt">(<a href="http://java.sun.com/j2se/1.4/docs/api/java/lang/String.html" title="class or interface in java.lang"><span style="font-size: 10.5pt">String</span></a>&nbsp;name, <a href="http://java.sun.com/j2se/1.4/docs/api/java/io/Reader.html" title="class or interface in java.io"><span style="font-size: 10.5pt">Reader</span></a>&nbsp;reader, <a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.TermVector.html" title="class in org.apache.lucene.document"><span style="font-size: 10.5pt">Field.TermVector</span></a>&nbsp;termVector)</span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-size: 12pt"><a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.html#Field%28java.lang.String,%20java.lang.String,%20org.apache.lucene.document.Field.Store,%20org.apache.lucene.document.Field.Index%29"><span style="font-size: 10.5pt">Field</span></a></span></strong><span style="font-size: 12pt">(<a href="http://java.sun.com/j2se/1.4/docs/api/java/lang/String.html" title="class or interface in java.lang"><span style="font-size: 10.5pt">String</span></a>&nbsp;name, <a href="http://java.sun.com/j2se/1.4/docs/api/java/lang/String.html" title="class or interface in java.lang"><span style="font-size: 10.5pt">String</span></a>&nbsp;value, <a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Store.html" title="class in org.apache.lucene.document"><span style="font-size: 10.5pt">Field.Store</span></a>&nbsp;store, <a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Index.html" title="class in org.apache.lucene.document"><span style="font-size: 10.5pt">Field.Index</span></a>&nbsp;index)</span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-size: 12pt"><a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.html#Field%28java.lang.String,%20java.lang.String,%20org.apache.lucene.document.Field.Store,%20org.apache.lucene.document.Field.Index,%20org.apache.lucene.document.Field.TermVector%29"><span style="font-size: 10.5pt">Field</span></a></span></strong><span style="font-size: 12pt">(<a href="http://java.sun.com/j2se/1.4/docs/api/java/lang/String.html" title="class or interface in java.lang"><span style="font-size: 10.5pt">String</span></a>&nbsp;name, <a href="http://java.sun.com/j2se/1.4/docs/api/java/lang/String.html" title="class or interface in java.lang"><span style="font-size: 10.5pt">String</span></a>&nbsp;value, <a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Store.html" title="class in org.apache.lucene.document"><span style="font-size: 10.5pt">Field.Store</span></a>&nbsp;store, <a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Index.html" title="class in org.apache.lucene.document"><span style="font-size: 10.5pt">Field.Index</span></a>&nbsp;index, <a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.TermVector.html" title="class in org.apache.lucene.document"><span style="font-size: 10.5pt">Field.TermVector</span></a>&nbsp;termVector)</span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span>在<span>Field</span>中有三个内部类：<span>Field.Index,Field.Store,Field.termVector</span>，而构造函数也用到了它们。</span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span>注意：</span></strong><strong><span style="font-size: 12pt">termVector</span></strong><strong><span style="font-size: 12pt">是<span>Lucene 1.4</span></span></strong><strong><span>新增的它提供一种向量机制来进行模糊查询的这个不常用，</span></strong></p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span>默认是<span>false</span>不过是什么对于一般查询无影响。</span></strong></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span>它们的不同的组合，在全文检索中有着不同的作用。看看下面的表吧<span>:</span></span></p>
<table class="MsoTableGrid" cellspacing="0" border="1" style="border: medium none ; width: 518.4pt; border-collapse: collapse" width="691" cellpadding="0">
    <tbody>
        <tr>
            <td valign="top" style="border: 1pt solid windowtext; padding: 0cm 5.4pt; width: 131.4pt" width="175">
            <p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">Field.Index</span></p>
            </td>
            <td valign="top" style="border-style: solid solid solid none; border-color: windowtext windowtext windowtext -moz-use-text-color; border-width: 1pt 1pt 1pt medium; padding: 0cm 5.4pt; width: 99pt" width="132">
            <p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">Field.Store</span></p>
            </td>
            <td valign="top" style="border-style: solid solid solid none; border-color: windowtext windowtext windowtext -moz-use-text-color; border-width: 1pt 1pt 1pt medium; padding: 0cm 5.4pt; width: 288pt" width="384">
            <p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">说明</span></p>
            </td>
        </tr>
        <tr>
            <td valign="top" style="border-style: none solid solid; border-color: -moz-use-text-color; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 131.4pt" width="175">
            <p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-size: 12pt"><a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Index.html#TOKENIZED"><span style="font-size: 10.5pt">TOKENIZED</span></a>(</span></strong><strong><span style="font-size: 12pt">分词<span>)</span></span></strong></p>
            </td>
            <td valign="top" style="border-style: none solid solid none; border-color: -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 99pt" width="132">
            <p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-size: 12pt"><a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Store.html#YES"><span style="font-size: 10.5pt">YES</span></a></span></strong></p>
            </td>
            <td valign="top" style="border-style: none solid solid none; border-color: -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 288pt" width="384">
            <p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">文章的标题或内容<span>(</span>如果是内容的话不能太长<span>)</span>是可以被搜索的</span></p>
            </td>
        </tr>
        <tr>
            <td valign="top" style="border-style: none solid solid; border-color: -moz-use-text-color; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 131.4pt" width="175">
            <p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-size: 12pt"><a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Index.html#TOKENIZED"><span style="font-size: 10.5pt">TOKENIZED</span></a></span></strong></p>
            </td>
            <td valign="top" style="border-style: none solid solid none; border-color: -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 99pt" width="132">
            <p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-size: 12pt"><a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Index.html#NO"><span style="font-size: 10.5pt">NO</span></a></span></strong></p>
            </td>
            <td valign="top" style="border-style: none solid solid none; border-color: -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 288pt" width="384">
            <p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">文章的标题或内容<span>(</span>内容可以很长<span>)</span>也是可以被看过的</span></p>
            </td>
        </tr>
        <tr>
            <td valign="top" style="border-style: none solid solid; border-color: -moz-use-text-color; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 131.4pt" width="175">
            <p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-size: 12pt"><a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Index.html#NO"><span style="font-size: 10.5pt">NO</span></a></span></strong></p>
            </td>
            <td valign="top" style="border-style: none solid solid none; border-color: -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 99pt" width="132">
            <p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-size: 12pt"><a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Store.html#YES"><span style="font-size: 10.5pt">YES</span></a></span></strong></p>
            </td>
            <td valign="top" style="border-style: none solid solid none; border-color: -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 288pt" width="384">
            <p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">这是不能被搜索的，它只是被搜索内容的附属物。如<span>URL</span>等</span></p>
            </td>
        </tr>
        <tr>
            <td valign="top" style="border-style: none solid solid; border-color: -moz-use-text-color; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 131.4pt" width="175">
            <p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-size: 12pt"><a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Index.html#UN_TOKENIZED"><span style="font-size: 10.5pt">UN_TOKENIZED</span></a></span></strong></p>
            </td>
            <td valign="top" style="border-style: none solid solid none; border-color: -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 99pt" width="132">
            <p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-size: 12pt">YES/NO</span></strong></p>
            </td>
            <td valign="top" style="border-style: none solid solid none; border-color: -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 288pt" width="384">
            <p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">不被分词，它作为一个整体被搜索<span>,</span>搜一部分是搜不出来的</span></p>
            </td>
        </tr>
        <tr>
            <td valign="top" style="border-style: none solid solid; border-color: -moz-use-text-color; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 131.4pt" width="175">
            <p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-size: 12pt"><a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Index.html#NO"><span style="font-size: 10.5pt">NO</span></a></span></strong></p>
            </td>
            <td valign="top" style="border-style: none solid solid none; border-color: -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 99pt" width="132">
            <p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-size: 12pt"><a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Index.html#NO"><span style="font-size: 10.5pt">NO</span></a></span></strong></p>
            </td>
            <td valign="top" style="border-style: none solid solid none; border-color: -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0cm 5.4pt; width: 288pt" width="384">
            <p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">没有这种用法</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">而对于</span><strong><span style="font-size: 12pt"><a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.html#Field%28java.lang.String,%20java.io.Reader%29"><span style="font-size: 10.5pt">Field</span></a></span></strong><span style="font-size: 12pt">(<a href="http://java.sun.com/j2se/1.4/docs/api/java/lang/String.html" title="class or interface in java.lang"><span style="font-size: 10.5pt">String</span></a>&nbsp;name, <a href="http://java.sun.com/j2se/1.4/docs/api/java/io/Reader.html" title="class or interface in java.io"><span style="font-size: 10.5pt">Reader</span></a>&nbsp;reader)</span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-size: 12pt; color: red"><a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.html#Field%28java.lang.String,%20java.io.Reader,%20org.apache.lucene.document.Field.TermVector%29"><span style="font-size: 10.5pt">Field</span></a></span></strong><strong><span style="font-size: 12pt; color: red">(<a href="http://java.sun.com/j2se/1.4/docs/api/java/lang/String.html" title="class or interface in java.lang"><span style="font-size: 10.5pt">String</span></a>&nbsp;name, <a href="http://java.sun.com/j2se/1.4/docs/api/java/io/Reader.html" title="class or interface in java.io"><span style="font-size: 10.5pt">Reader</span></a>&nbsp;reader, <a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.TermVector.html" title="class in org.apache.lucene.document"><span style="font-size: 10.5pt">Field.TermVector</span></a>&nbsp;termVector)</span></strong></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-family: 宋体; color: red">他们是<span>Field.Index.TOKENIZED</span>和<span>Field.Store.NO</span>的。这就是为什么我们在上面的例子中会</span></strong></p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-family: 宋体; color: red">出现文章的内容为<span>null</span>了。因为它只是被索引了，而并没有被存储下来。如果一定要看到文章的</span></strong></p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-family: 宋体; color: red">内容的话可以通过文章的路径得到毕竟文章的路径是作为搜索的附属物被搜索出来了。<u><span style="border: 1pt solid windowtext; padding: 0cm; background: #d9d9d9 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">而我们在</span></u></span></strong></p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-family: 宋体; color: red"><u><span style="border: 1pt solid windowtext; padding: 0cm; background: #d9d9d9 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>Web</span>开发的时候一般是将大数据放在数据库中，不会放在文件系统中，更不会放在索引目录里，</span></u></span></strong></p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-family: 宋体; color: red"><u><span style="border: 1pt solid windowtext; padding: 0cm; background: #d9d9d9 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">因为它太大了操作会加大服务器的负担</span></u><em>。</em></span></strong></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">下面介绍一下<span>IndexWriter:</span></span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">它就是一个写入索引的写入器<span>,</span>它的任务比较简单：</span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">1.</span><span style="font-family: 宋体; color: black">用<span>addDocument()</span>将已经准备好写入索引的<span>document</span>们加入</span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">2.</span><span style="font-family: 宋体; color: black">调用<span>close()</span>将索引写入索引目录</span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><span style="font-family: 宋体; color: black">先看一下它的构造函数<span>:</span></span></p>
<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><strong><span style="font-size: 12pt"><a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/index/IndexWriter.html#IndexWriter%28org.apache.lucene.store.Directory,%20org.apache.lucene.analysis.Analyzer,%20boolean%29"><span style="font-size: 10.5pt">IndexWriter</span></a></span></strong><span style="font-size: 12pt">(<a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/store/Directory.html" title="class in org.apache.lucene.store"><span style="font-size: 10.5pt">Directory</span></a>&nbsp;d, <a href="http://likunkun.javaeye.com/blog/%C3%91%C2%A7%C3%8F%C2%B0%C3%97%C3%8A%C3%81%C3%8F/luence/lucene-2.0.0/docs/api/org/apache/lucene/analysis/Analyzer.html" title="class in org.apache.lucene.analysis"><span style="font-size: 10.5pt">Analyzer</span></a>&nbsp;a, boolean&nbsp;create)</span></p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left">
IndexWriter(File path, Analyzer a, boolean create)<br />
IndexWriter(String path, Analyzer a, boolean create)<br />
可见构造它需要一个索引文件目录，一个分析器(一般用标准的这个)，最后一个参数是标识是否清空索引目录<br />
它有一些设置参数的功能如：设置Field的最大长度<br />
看个例子：</p><pre name="code" class="java">public void IndexMaxField() throws IOException
{
        IndexWriter indexWriter= new IndexWriter(&quot;c:\\index&quot;,new StandardAnalyzer(),true);
        Document doc1 = new Document();
        doc1.add(new Field(&quot;name1&quot;,&quot;程序员之家&quot;,Field.Store.YES,Field.Index.TOKENIZED));
        Document doc2 = new Document();
        doc2.add(new Field(&quot;name2&quot;,&quot;Welcome to the Home of programers&quot;,Field.Store.YES,Field.Index.TOKENIZED));
        indexWriter.setMaxFieldLength(5);
        indexWriter.addDocument(doc1);
        indexWriter.setMaxFieldLength(3);
        indexWriter.addDocument(doc1);
        indexWriter.setMaxFieldLength(0);
        indexWriter.addDocument(doc2);
        indexWriter.setMaxFieldLength(3);
        indexWriter.addDocument(doc2);
        indexWriter.close();
}
public void SearcherMaxField() throws ParseException, IOException
{
        Query query = null;
        Hits hits = null;
        IndexSearcher indexSearcher= null;
        QueryParser queryParser= null;
        queryParser = new QueryParser(&quot;name1&quot;,new StandardAnalyzer());
        query = queryParser.parse(&quot;程序员&quot;);
        indexSearcher= new IndexSearcher(&quot;c:\\index&quot;);
        hits = indexSearcher.search(query);
        System.out.println(&quot;您搜的是：程序员&quot;);
        System.out.println(&quot;找到了&quot;+hits.length()+&quot;个结果&quot;);
        System.out.println(&quot;它们分别是：&quot;);
        for (int i = 0; i &lt; hits.length(); i++)
        {
            Document doc = hits.doc(i);
            System.out.println(doc.get(&quot;name1&quot;));
        }
        query = queryParser.parse(&quot;程序员之家&quot;);
        indexSearcher= new IndexSearcher(&quot;c:\\index&quot;);
        hits = indexSearcher.search(query);
        System.out.println(&quot;您搜的是：程序员之家&quot;);
        System.out.println(&quot;找到了&quot;+hits.length()+&quot;个结果&quot;);
        System.out.println(&quot;它们分别是：&quot;);
        for (int i = 0; i &lt; hits.length(); i++)
        {
            Document doc = hits.doc(i);
            System.out.println(doc.get(&quot;name1&quot;));
        }
        queryParser = new QueryParser(&quot;name2&quot;,new StandardAnalyzer());
        query = queryParser.parse(&quot;Welcome&quot;);
        indexSearcher= new IndexSearcher(&quot;c:\\index&quot;);
        hits = indexSearcher.search(query);
        System.out.println(&quot;您搜的是：Welcome&quot;);
        System.out.println(&quot;找到了&quot;+hits.length()+&quot;个结果&quot;);
        System.out.println(&quot;它们分别是：&quot;);
        for (int i = 0; i &lt; hits.length(); i++)
        {
            Document doc = hits.doc(i);
            System.out.println(doc.get(&quot;name2&quot;));
        }           
        query = queryParser.parse(&quot;the&quot;);
        indexSearcher= new IndexSearcher(&quot;c:\\index&quot;);
        hits = indexSearcher.search(query);
        System.out.println(&quot;您搜的是：the&quot;);
        System.out.println(&quot;找到了&quot;+hits.length()+&quot;个结果&quot;);
        System.out.println(&quot;它们分别是：&quot;);
        for (int i = 0; i &lt; hits.length(); i++)
        {
            Document doc = hits.doc(i);
            System.out.println(doc.get(&quot;name2&quot;));
        }
        query = queryParser.parse(&quot;home&quot;);
        indexSearcher= new IndexSearcher(&quot;c:\\index&quot;);
        hits = indexSearcher.search(query);
        System.out.println(&quot;您搜的是：home&quot;);
        System.out.println(&quot;找到了&quot;+hits.length()+&quot;个结果&quot;);
        System.out.println(&quot;它们分别是：&quot;);
        for (int i = 0; i &lt; hits.length(); i++)
        {
            Document doc = hits.doc(i);
            System.out.println(doc.get(&quot;name2&quot;));
        }
}</pre>&nbsp;<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><br />
它的运行结果为:<br />
总结一下：<br />
1.设置Field的长度限制只是限制了搜索。如果用了Field.Store.YES的话还是会<br />
全部被保存进索引目录里的。<br />
2.为什么搜the没有搜出来呢是因为lucene分析英文的时候不会搜索the to of 等无<br />
用的词(搜这些词是无意义的)。<br />
3.New StandardAnlayzer()对于英文的分词是按空格和一些无用的词，而中文呢是全部的单个<br />
的字。<br />
4.设置Field的最大长度是以0开头和数组一样。<br />
程序员之家----------3--------程序员之<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 1 2&nbsp; 3<br />
Welcome to the home of programmers------3------Welcome to the home of programmers<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2<br />
大家还可以试一下别的，以便加深一下印象 </p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left">&nbsp;</p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left">
到现在我们已经可以用lucene建立索引了<br />
下面介绍一下几个功能来完善一下：<br />
1．索引格式<br />
其实索引目录有两种格式，一种是除配置文件外，每一个Document独立成为一个文件</p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left">（这种搜索起来会影响速度）。另一种是全部的Document成一个文件，这样属于复合模式就快了。<br />
2.索引文件可放的位置：<br />
索引可以存放在两个地方1.硬盘，2.内存<br />
放在硬盘上可以用FSDirectory()，放在内存的用RAMDirectory()不过一关机就没了<br />
FSDirectory.getDirectory(File file, boolean create)<br />
FSDirectory.getDirectory(String path, boolean create)两个工厂方法返回目录<br />
New RAMDirectory()就直接可以<br />
再和IndexWriter(Directory d, Analyzer a, boolean create)一配合就行了<br />
如：<br />
IndexWrtier indexWriter = new IndexWriter(FSDirectory.getDirectory(&ldquo;c:\\index&rdquo;,true),new StandardAnlyazer(),true);<br />
IndexWrtier indexWriter = new IndexWriter(new RAMDirectory(),new StandardAnlyazer(),true);<br />
3.索引的合并<br />
这个可用IndexWriter.addIndexes(Directory[] dirs)将目录加进去<br />
来看个例子:</p><pre name="code" class="java">public void UniteIndex() throws IOException
    {
        IndexWriter writerDisk = new IndexWriter(FSDirectory.getDirectory(&quot;c:\\indexDisk&quot;, true),new StandardAnalyzer(),true);
        Document docDisk = new Document();
        docDisk.add(new Field(&quot;name&quot;,&quot;程序员之家&quot;,Field.Store.YES,Field.Index.TOKENIZED));
        writerDisk.addDocument(docDisk);
        RAMDirectory ramDir = new RAMDirectory();
        IndexWriter writerRam = new IndexWriter(ramDir,new StandardAnalyzer(),true);
        Document docRam = new Document();
        docRam.add(new Field(&quot;name&quot;,&quot;程序员杂志&quot;,Field.Store.YES,Field.Index.TOKENIZED));
        writerRam.addDocument(docRam);
        writerRam.close();//这个方法非常重要，是必须调用的
        writerDisk.addIndexes(new Directory[]{ramDir});
        writerDisk.close();
    }
    public void UniteSearch() throws ParseException, IOException
    {
        QueryParser queryParser = new QueryParser(&quot;name&quot;,new StandardAnalyzer());
        Query query = queryParser.parse(&quot;程序员&quot;);
        IndexSearcher indexSearcher =new IndexSearcher(&quot;c:\\indexDisk&quot;);
        Hits hits = indexSearcher.search(query);
        System.out.println(&quot;找到了&quot;+hits.length()+&quot;结果&quot;);
        for(int i=0;i
        {
            Document doc = hits.doc(i);
            System.out.println(doc.get(&quot;name&quot;));
        }
}</pre>&nbsp;<p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left"><br />
这个例子是将内存中的索引合并到硬盘上来.<br />
注意：合并的时候一定要将被合并的那一方的IndexWriter的close()方法调用。<br />
4.对索引的其它操作:<br />
IndexReader类是用来操作索引的，它有对Document,Field的删除等操作。<br />
下面一部分的内容是：全文的搜索<br />
全文的搜索主要是用：IndexSearcher,Query,Hits,Document(都是Query的子类),</p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left">有的时候用QueryParser<br />
主要步骤：<br />
1.new QueryParser(Field字段，new 分析器)<br />
2.Query query = QueryParser.parser(&ldquo;要查询的字串&rdquo;);这个地方我们可以用反射api看一下</p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left">query究竟是什么类型<br />
3.new IndexSearcher(索引目录).search(query);返回Hits<br />
4.用Hits.doc(n);可以遍历出Document<br />
5.用Document可得到Field的具体信息了。<br />
其实1　，2两步就是为了弄出个Query 实例，究竟是什么类型的看分析器了。<br />
拿以前的例子来说吧<br />
QueryParser queryParser = new QueryParser(&quot;name&quot;,new StandardAnalyzer());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Query query = queryParser.parse(&quot;程序员&quot;);<br />
/*这里返回的就是org.apache.lucene.search.PhraseQuery*/<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IndexSearcher indexSearcher =new IndexSearcher(&quot;c:\\indexDisk&quot;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Hits hits = indexSearcher.search(query);<br />
不管是什么类型，无非返回的就是Query的子类，我们完全可以不用这两步直接new个Query的子</p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left">类的实例就ok了，</p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left">不过一般还是用这两步因为它返回
的是PhraseQuery这个是非常强大的query子类它可以进行多字搜索用</p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left">QueryParser可以设置各个关键字之间的关系这个是最常用的了。<br />
IndexSearcher:<br />
其实IndexSearcher它内部自带了一个IndexReader用来读取索引的，IndexSearcher有个close()方法，</p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left">这个方法不是用来关闭IndexSearche的是用来关闭自带的IndexReader。<br />
<br />
QueryParser呢可以用parser.setOperator()来设置各个关键字之间的关系（与还是或）</p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left">它可以自动通过空格从字串里面将关键字分离出来。<br />
注意：用QueryParser搜索的时候分析器一定的和建立索引时候用的分析器是一样的。<br />
Query:<br />
可以看一个lucene2.0的帮助文档有很多的子类:<br />
BooleanQuery, ConstantScoreQuery, ConstantScoreRangeQuery,
</p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left">DisjunctionMaxQuery, FilteredQuery, MatchAllDocsQuery,
MultiPhraseQuery, </p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left">MultiTermQuery, PhraseQuery, PrefixQuery, RangeQuery,
SpanQuery, TermQuery<br />
各自有用法看一下文档就能知道它们的用法了<br />
下面一部分讲一下lucene的分析器:<br />
分析器是由分词器和过滤器组成的，拿英文来说吧分词器就是通过空格把单词分开，</p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left">过滤器就是把the,to,of等词去掉不被搜索和索引。<br />
我们最常用的是StandardAnalyzer()它是lucene的标准分析器它集成了内部的许多的分析器。<br />
最后一部分了：lucene的高级搜索了<br />
1.排序<br />
Lucene有内置的排序用IndexSearcher.search(query,sort)但是功能并不理想。</p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left">我们需要自己实现自定义的排序。<br />
这样的话得实现两个接口: ScoreDocComparator, SortComparatorSource<br />
用IndexSearcher.search(query,new Sort(new SortField(String Field,SortComparatorSource)));<br />
就看个例子吧：<br />
这是一个建立索引的例子：</p><pre name="code" class="java">public void IndexSort() throws IOException
{
        IndexWriter writer = new IndexWriter(&quot;C:\\indexStore&quot;,new StandardAnalyzer(),true);
        Document doc = new Document()
        doc.add(new Field(&quot;sort&quot;,&quot;1&quot;,Field.Store.YES,Field.Index.TOKENIZED));
        writer.addDocument(doc);
        doc = new Document();
        doc.add(new Field(&quot;sort&quot;,&quot;4&quot;,Field.Store.YES,Field.Index.TOKENIZED));
        writer.addDocument(doc);
        doc = new Document();
        doc.add(new Field(&quot;sort&quot;,&quot;3&quot;,Field.Store.YES,Field.Index.TOKENIZED));
        writer.addDocument(doc);
        doc = new Document();
        doc.add(new Field(&quot;sort&quot;,&quot;5&quot;,Field.Store.YES,Field.Index.TOKENIZED));
        writer.addDocument(doc);
        doc = new Document();
        doc.add(new Field(&quot;sort&quot;,&quot;9&quot;,Field.Store.YES,Field.Index.TOKENIZED));
        writer.addDocument(doc);
        doc = new Document();
        doc.add(new Field(&quot;sort&quot;,&quot;6&quot;,Field.Store.YES,Field.Index.TOKENIZED));
        writer.addDocument(doc);
        doc = new Document();
        doc.add(new Field(&quot;sort&quot;,&quot;7&quot;,Field.Store.YES,Field.Index.TOKENIZED));
        writer.addDocument(doc);
        writer.close();
} </pre><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp; </p><pre name="code" class="java">public void SearchSort1() throws IOException, ParseException
{
        IndexSearcher indexSearcher = new IndexSearcher(&quot;C:\\indexStore&quot;);
        QueryParser queryParser = new QueryParser(&quot;sort&quot;,new StandardAnalyzer());
        Query query = queryParser.parse(&quot;4&quot;);
       
        Hits hits = indexSearcher.search(query);
        System.out.println(&quot;有&quot;+hits.length()+&quot;个结果&quot;);
        Document doc = hits.doc(0);
        System.out.println(doc.get(&quot;sort&quot;));
}
public void SearchSort2() throws IOException, ParseException
{
        IndexSearcher indexSearcher = new IndexSearcher(&quot;C:\\indexStore&quot;);
        Query query = new RangeQuery(new Term(&quot;sort&quot;,&quot;1&quot;),new Term(&quot;sort&quot;,&quot;9&quot;),true);//这个地方前面没有提到，它是用于范围的Query可以看一下帮助文档.
        Hits hits = indexSearcher.search(query,new Sort(new SortField(&quot;sort&quot;,new MySortComparatorSource())));
        System.out.println(&quot;有&quot;+hits.length()+&quot;个结果&quot;);
        for(int i=0;i
        {
            Document doc = hits.doc(i);
            System.out.println(doc.get(&quot;sort&quot;));
        }
}</pre>&nbsp;<p>&nbsp;</p><pre name="code" class="java">public class MyScoreDocComparator implements ScoreDocComparator
{
    private Integer[]sort;
    public MyScoreDocComparator(String s,IndexReader reader, String fieldname) throws IOException
    {
        sort = new Integer[reader.maxDoc()];
        for(int i = 0;i
        {
            Document doc =reader.document(i);
            sort[i]=new Integer(doc.get(&quot;sort&quot;));
        }
    }
    public int compare(ScoreDoc i, ScoreDoc j)
    {
        if(sort[i.doc]&gt;sort[j.doc])
            return 1;
        if(sort[i.doc]&lt;sort[j.doc])
            return -1;
        return 0;
    }
    public int sortType()
    {
        return SortField.INT;
    }
    public Comparable sortValue(ScoreDoc i)
    {
        // TODO 自动生成方法存根
        return new Integer(sort[i.doc]);
    }
}
public class MySortComparatorSource implements SortComparatorSource
{
    private static final long serialVersionUID = -9189690812107968361L;
    public ScoreDocComparator newComparator(IndexReader reader, String fieldname)
            throws IOException
    {
        if(fieldname.equals(&quot;sort&quot;))
            return new MyScoreDocComparator(&quot;sort&quot;,reader,fieldname);
        return null;
    }
}</pre>&nbsp;<p><br />
SearchSort1()输出的结果没有排序,SearchSort2()就排序了。<br />
2.多域搜索MultiFieldQueryParser<br />
如果想输入关键字而不想关心是在哪个Field里的就可以用MultiFieldQueryParser了<br />
用它的构造函数即可后面的和一个Field一样。<br />
MultiFieldQueryParser. parse(String[] queries, String[] fields,
BooleanClause.Occur[] flags, Analyzer
analyzer)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ~~~~~~~~~~~~~~~~~<br />
第三个参数比较特殊这里也是与以前<span class="hilite1"><span class="hilite1">lucene</span></span>1.4.3不一样的地方<br />
看一个例子就知道了<br />
String[] fields = {&quot;filename&quot;, &quot;contents&quot;, &quot;description&quot;};<br />
&nbsp;BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BooleanClause.Occur.MUST,//在这个Field里必须出现的<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BooleanClause.Occur.MUST_NOT};//在这个Field里不能出现<br />
&nbsp;MultiFieldQueryParser.parse(&quot;query&quot;, fields, flags, analyzer);</p><p class="MsoNormal" align="left" style="margin-right: -88.6pt; text-align: left">&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://longdick.javaeye.com/blog/170222#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 11 Mar 2008 16:16:01 +0800</pubDate>
        <link>http://longdick.javaeye.com/blog/170222</link>
        <guid>http://longdick.javaeye.com/blog/170222</guid>
      </item>
      <item>
        <title>[转]深入 Lucene 索引机制</title>
        <author>longdick</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://longdick.javaeye.com">longdick</a>&nbsp;
          链接：<a href="http://longdick.javaeye.com/blog/169116" style="color:red;">http://longdick.javaeye.com/blog/169116</a>&nbsp;
          发表时间: 2008年03月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <blockquote>
<p>&nbsp;</p>
<p>Lucene 是一个基于 Java 的全文检索工具包，你可以利用它来为你的应用程序加入索引和检索功能。Lucene 目前是著名的 Apache Jakarta 家族中的一个开源项目，下面我们即将学习 Lucene 的索引机制以及它的索引文件的结构。</p>
<p>在这篇文章中，我们首先演示如何使用 Lucene 来索引文档，接着讨论如何提高索引的性能。最后我们来分析 Lucene 的索引文件结构。需要记住的是，Lucene 不是一个完整的应用程序，而是一个信息检索包，它方便你为你的应用程序添加索引和搜索功能。</p>
</blockquote>
<!-- START RESERVED FOR FUTURE USE INCLUDE FILES--><!--  include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters -->
<!-- END RESERVED FOR FUTURE USE INCLUDE FILES-->
<p><a name="N10053" title="N10053"></a>
<span class="atitle">架构概览</span>
</p>
<p>图一显示了 Lucene 的索引机制的架构。Lucene 使用各种解析器对各种不同类型的文档进行解析。比如对于 HTML 文档，HTML
解析器会做一些预处理的工作，比如过滤文档中的 HTML 标签等等。HTML 解析器的输出的是文本内容，接着 Lucene
的分词器(Analyzer)从文本内容中提取出索引项以及相关信息，比如索引项的出现频率。接着 Lucene 的分词器把这些信息写到索引文件中。</p>
<p>

<br />
<a name="N1005E" title="N1005E"></a>
<strong>图一：Lucene 索引机制架构</strong>
<br />
<img src="http://www.ibm.com/developerworks/cn/java/wa-lucene/images/image002.jpg" border="0" height="345" alt="图一：Lucene 索引机制架构" width="438" />
<br /></p>
<table cellspacing="0" border="0" width="100%" cellpadding="0">
<tbody>
<tr>
<td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" alt="" width="100%" />
<br />
<img src="http://www.ibm.com/i/c.gif" border="0" height="6" alt="" width="8" />
</td>
</tr>
</tbody>
</table>
<table class="no-print" cellspacing="0" border="0" align="right" cellpadding="0">
<tbody>
<tr align="right">
<td><img src="http://www.ibm.com/i/c.gif" height="4" alt="" width="100%" />
<br />
<table cellspacing="0" border="0" cellpadding="0">
<tbody>
<tr>
<td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" alt="" width="16" />
<br />
</td>
<td align="right" valign="top"><a href="http://www.ibm.com/developerworks/cn/java/wa-lucene/index.html#main" class="fbox"><strong>回页首</strong>
</a>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p><br /></p>
<p><a name="N1006E" title="N1006E"></a>
<span class="atitle">用Lucene索引文档</span>
</p>
<p>接下来我将一步一步的来演示如何利用 Lucene 为你的文档创建索引。只要你能将要索引的文件转化成文本格式，Lucene
就能为你的文档建立索引。比如，如果你想为 HTML 文档或者 PDF
文档建立索引，那么首先你就需要从这些文档中提取出文本信息，然后把文本信息交给 Lucene 建立索引。我们接下来的例子用来演示如何利用
Lucene 为后缀名为 txt 的文件建立索引。</p>
<p>1．	准备文本文件</p>
<p>首先把一些以 txt 为后缀名的文本文件放到一个目录中，比如在 Windows 平台上，你可以放到 C:\\files_to_index 下面。</p>
<p>2．	创建索引</p>
<p>清单1是为我们所准备的文档创建索引的代码。</p>
<p>
<br />
<a name="N10083" title="N10083"></a>
<strong>清单1：用 Lucene 索引你的文档</strong></p>
<table cellspacing="0" border="0" width="100%" cellpadding="0">
<tbody>
<tr>
<td class="code-outline">
<pre class="displaycode">package lucene.index;

import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import java.util.Date;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;

/**
 * This class demonstrates the process of creating an index with Lucene 
 * for text files in a directory.
 */
public class TextFileIndexer {
 public static void main(String[] args) throws Exception{
   //fileDir is the directory that contains the text files to be indexed
   File   fileDir  = new File(&quot;C:\\files_to_index &quot;);

   //indexDir is the directory that hosts Lucene's index files
   File   indexDir = new File(&quot;C:\\luceneIndex&quot;);
   Analyzer luceneAnalyzer = new StandardAnalyzer();
   IndexWriter indexWriter = new IndexWriter(indexDir,luceneAnalyzer,true);
   File[] textFiles  = fileDir.listFiles();
   long startTime = new Date().getTime();

   //Add documents to the index
   for(int i = 0; i &lt; textFiles.length; i++){
     if(textFiles[i].isFile() &gt;&gt; textFiles[i].getName().endsWith(&quot;.txt&quot;)){
       System.out.println(&quot;File &quot; + textFiles[i].getCanonicalPath() 
              + &quot; is being indexed&quot;);
       Reader textReader = new FileReader(textFiles[i]);
       Document document = new Document();
       document.add(Field.Text(&quot;content&quot;,textReader));
       document.add(Field.Text(&quot;path&quot;,textFiles[i].getPath()));
       indexWriter.addDocument(document);
     }
   }

   indexWriter.optimize();
   indexWriter.close();
   long endTime = new Date().getTime();

   System.out.println(&quot;It took &quot; + (endTime - startTime) 
              + &quot; milliseconds to create an index for the files in the directory &quot;
              + fileDir.getPath());
  }
}
</pre>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>正如清单1所示，你可以利用 Lucene 非常方便的为文档创建索引。接下来我们分析一下清单1中的比较关键的代码，我们先从下面的一条语句开始看起。</p>
<p>&nbsp;</p>
<table cellspacing="0" border="0" width="100%" cellpadding="0">
<tbody>
<tr>
<td class="code-outline">
<pre class="displaycode">Analyzer luceneAnalyzer = new StandardAnalyzer();
</pre>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>这条语句创建了类 StandardAnalyzer 的一个实例，这个类是用来从文本中提取出索引项的。它只是抽象类 Analyzer 的其中一个实现。Analyzer 也有一些其它的子类，比如 SimpleAnalyzer 等。</p>
<p>我们接着看另外一条语句：</p>
<p>&nbsp;</p>
<table cellspacing="0" border="0" width="100%" cellpadding="0">
<tbody>
<tr>
<td class="code-outline">
<pre class="displaycode">IndexWriter indexWriter = new IndexWriter(indexDir,luceneAnalyzer,true);
</pre>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>这条语句创建了类 IndexWriter 的一个实例，该类也是 Lucene
索引机制里面的一个关键类。这个类能创建一个新的索引或者打开一个已存在的索引并为该所引添加文档。我们注意到该类的构造函数接受三个参数，第一个参数指
定了存储索引文件的路径。第二个参数指定了在索引过程中使用什么样的分词器。最后一个参数是个布尔变量，如果值为真，那么就表示要创建一个新的索引，如果
值为假，就表示打开一个已经存在的索引。</p>
<p>接下来的代码演示了如何添加一个文档到索引文件中。</p>
<p>&nbsp;</p>
<table cellspacing="0" border="0" width="100%" cellpadding="0">
<tbody>
<tr>
<td class="code-outline">
<pre class="displaycode">Document document = new Document();
document.add(Field.Text(&quot;content&quot;,textReader));
document.add(Field.Text(&quot;path&quot;,textFiles[i].getPath()));
indexWriter.addDocument(document);
</pre>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>首先第一行创建了类 Document
的一个实例，它由一个或者多个的域(Field)组成。你可以把这个类想象成代表了一个实际的文档，比如一个 HTML 页面，一个 PDF
文档，或者一个文本文件。而类 Document 中的域一般就是实际文档的一些属性。比如对于一个 HTML
页面，它的域可能包括标题，内容，URL 等。我们可以用不同类型的 Field
来控制文档的哪些内容应该索引，哪些内容应该存储。如果想获取更多的关于 Lucene 的域的信息，可以参考 Lucene
的帮助文档。代码的第二行和第三行为文档添加了两个域，每个域包含两个属性，分别是域的名字和域的内容。在我们的例子中两个域的名字分别是
&quot;content&quot;和&quot;path&quot;。分别存储了我们需要索引的文本文件的内容和路径。最后一行把准备好的文档添加到了索引当中。</p>
<p>当我们把文档添加到索引中后，不要忘记关闭索引，这样才保证 Lucene 把添加的文档写回到硬盘上。下面的一句代码演示了如何关闭索引。</p>
<p>&nbsp;</p>
<table cellspacing="0" border="0" width="100%" cellpadding="0">
<tbody>
<tr>
<td class="code-outline">
<pre class="displaycode">indexWriter.close();
</pre>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>利用清单1中的代码，你就可以成功的将文本文档添加到索引中去。接下来我们看看对索引进行的另外一种重要的操作，从索引中删除文档。</p>
<p>&nbsp;</p>
<table cellspacing="0" border="0" width="100%" cellpadding="0">
<tbody>
<tr>
<td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" alt="" width="100%" />
<br />
<img src="http://www.ibm.com/i/c.gif" border="0" height="6" alt="" width="8" />
</td>
</tr>
</tbody>
</table>
<table class="no-print" cellspacing="0" border="0" align="right" cellpadding="0">
<tbody>
<tr align="right">
<td><img src="http://www.ibm.com/i/c.gif" height="4" alt="" width="100%" />
<br />
<table cellspacing="0" border="0" cellpadding="0">
<tbody>
<tr>
<td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" alt="" width="16" />
<br />
</td>
<td align="right" valign="top"><a href="http://www.ibm.com/developerworks/cn/java/wa-lucene/index.html#main" class="fbox"><strong>回页首</strong>
</a>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p><br /></p>
<p><a name="N100C9" title="N100C9"></a>
<span class="atitle">从索引中删除文档</span>
</p>
<p>类IndexReader负责从一个已经存在的索引中删除文档，如清单2所示。</p>
<p>
<br />
<a name="N100D2" title="N100D2"></a>
<strong>清单2：从索引中删除文档</strong></p>
<table cellspacing="0" border="0" width="100%" cellpadding="0">
<tbody>
<tr>
<td class="code-outline">
<pre class="displaycode">File   indexDir = new File(&quot;C:\\luceneIndex&quot;);
IndexReader ir = IndexReader.open(indexDir);
ir.delete(1);
ir.delete(new Term(&quot;path&quot;,&quot;C:\\file_to_index\lucene.txt&quot;));
ir.close();
</pre>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>在清单2中，第二行用静态方法 IndexReader.open(indexDir) 初始化了类 IndexReader
的一个实例，这个方法的参数指定了索引的存储路径。类 IndexReader
提供了两种方法去删除一个文档，如程序中的第三行和第四行所示。第三行利用文档的编号来删除文档。每个文档都有一个系统自动生成的编号。第四行删除了路径
为&quot;C:\\file_to_index\lucene.txt&quot;的文档。你可以通过指定文件路径来方便的删除一个文档。值得注意的是虽然利用上述代码删
除文档使得该文档不能被检索到，但是并没有物理上删除该文档。Lucene 只是通过一个后缀名为 .delete
的文件来标记哪些文档已经被删除。既然没有物理上删除，我们可以方便的把这些标记为删除的文档恢复过来，如清单 3
所示，首先打开一个索引，然后调用方法 ir.undeleteAll() 来完成恢复工作。</p>
<p>

<br />
<a name="N100DF" title="N100DF"></a>
<strong>清单3：恢复已删除文档</strong></p>
<table cellspacing="0" border="0" width="100%" cellpadding="0">
<tbody>
<tr>
<td class="code-outline">
<pre class="displaycode">File   indexDir = new File(&quot;C:\\luceneIndex&quot;);
IndexReader ir = IndexReader.open(indexDir);
ir.undeleteAll();
ir.close();
</pre>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>你现在也许想知道如何物理上删除索引中的文档，方法也非常简单。清单 4 演示了这个过程。</p>
<p>
<br />
<a name="N100EC" title="N100EC"></a>
<strong>清单4：如何物理上删除文档</strong></p>
<table cellspacing="0" border="0" width="100%" cellpadding="0">
<tbody>
<tr>
<td class="code-outline">
<pre class="displaycode">File   indexDir = new File(&quot;C:\\luceneIndex&quot;);
Analyzer luceneAnalyzer = new StandardAnalyzer();
IndexWriter indexWriter = new IndexWriter(indexDir,luceneAnalyzer,false);
indexWriter.optimize();
indexWriter.close();
</pre>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>在清单 4 中，第三行创建了类 IndexWriter 的一个实例，并且打开了一个已经存在的索引。第 4 行对索引进行清理，清理过程中将把所有标记为删除的文档物理删除。</p>
<p>Lucene 没有直接提供方法对文档进行更新，如果你需要更新一个文档，那么你首先需要把这个文档从索引中删除，然后把新版本的文档加入到索引中去。</p>
<p>&nbsp;</p>
<table cellspacing="0" border="0" width="100%" cellpadding="0">
<tbody>
<tr>
<td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" alt="" width="100%" />
<br />
<img src="http://www.ibm.com/i/c.gif" border="0" height="6" alt="" width="8" />
</td>
</tr>
</tbody>
</table>
<table class="no-print" cellspacing="0" border="0" align="right" cellpadding="0">
<tbody>
<tr align="right">
<td><img src="http://www.ibm.com/i/c.gif" height="4" alt="" width="100%" />
<br />
<table cellspacing="0" border="0" cellpadding="0">
<tbody>
<tr>
<td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" alt="" width="16" />
<br />
</td>
<td align="right" valign="top"><a href="http://www.ibm.com/developerworks/cn/java/wa-lucene/index.html#main" class="fbox"><strong>回页首</strong>
</a>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p><br /></p>
<p><a name="N100FC" title="N100FC"></a>
<span class="atitle">提高索引性能</span>
</p>
<p>利用
Lucene，在创建索引的工程中你可以充分利用机器的硬件资源来提高索引的效率。当你需要索引大量的文件时，你会注意到索引过程的瓶颈是在往磁盘上写索
引文件的过程中。为了解决这个问题, Lucene 在内存中持有一块缓冲区。但我们如何控制 Lucene 的缓冲区呢？幸运的是，Lucene
的类 IndexWriter 提供了三个参数用来调整缓冲区的大小以及往磁盘上写索引文件的频率。</p>
<p>1．合并因子（mergeFactor）</p>
<p>这个参数决定了在 Lucene 的一个索引块中可以存放多少文档以及把磁盘上的索引块合并成一个大的索引块的频率。比如，如果合并因子的值是
10，那么当内存中的文档数达到 10 的时候所有的文档都必须写到磁盘上的一个新的索引块中。并且，如果磁盘上的索引块的隔数达到 10 的话，这
10 个索引块会被合并成一个新的索引块。这个参数的默认值是
10，如果需要索引的文档数非常多的话这个值将是非常不合适的。对批处理的索引来讲，为这个参数赋一个比较大的值会得到比较好的索引效果。</p>
<p>2．最小合并文档数</p>
<p>这个参数也会影响索引的性能。它决定了内存中的文档数至少达到多少才能将它们写回磁盘。这个参数的默认值是10，如果你有足够的内存，那么将这个值尽量设的比较大一些将会显著的提高索引性能。</p>
<p>3．最大合并文档数</p>
<p>这个参数决定了一个索引块中的最大的文档数。它的默认值是 Integer.MAX_VALUE，将这个参数设置为比较大的值可以提高索引效率和检索速度，由于该参数的默认值是整型的最大值，所以我们一般不需要改动这个参数。</p>
<p>清单 5 列出了这个三个参数用法，清单 5 和清单 1 非常相似，除了清单 5 中会设置刚才提到的三个参数。</p>
<p>
<br />
<a name="N1011A" title="N1011A"></a>
<strong>清单5：提高索引性能</strong></p>
<table cellspacing="0" border="0" width="100%" cellpadding="0">
<tbody>
<tr>
<td class="code-outline">
<pre class="displaycode">/**
 * This class demonstrates how to improve the indexing performance 
 * by adjusting the parameters provided by IndexWriter.
 */
public class AdvancedTextFileIndexer  {
  public static void main(String[] args) throws Exception{
    //fileDir is the directory that contains the text files to be indexed
    File   fileDir  = new File(&quot;C:\\files_to_index&quot;);

    //indexDir is the directory that hosts Lucene's index files
    File   indexDir = new File(&quot;C:\\luceneIndex&quot;);
    Analyzer luceneAnalyzer = new StandardAnalyzer();
    File[] textFiles  = fileDir.listFiles();
    long startTime = new Date().getTime();

    int mergeFactor = 10;
    int minMergeDocs = 10;
    int maxMergeDocs = Integer.MAX_VALUE;
    IndexWriter indexWriter = new IndexWriter(indexDir,luceneAnalyzer,true);        
    indexWriter.mergeFactor = mergeFactor;
    indexWriter.minMergeDocs = minMergeDocs;
    indexWriter.maxMergeDocs = maxMergeDocs;

    //Add documents to the index
    for(int i = 0; i &lt; textFiles.length; i++){
      if(textFiles[i].isFile() &gt;&gt; textFiles[i].getName().endsWith(&quot;.txt&quot;)){
        Reader textReader = new FileReader(textFiles[i]);
        Document document = new Document();
        document.add(Field.Text(&quot;content&quot;,textReader));
        document.add(Field.Keyword(&quot;path&quot;,textFiles[i].getPath()));
        indexWriter.addDocument(document);
      }
    }

    indexWriter.optimize();
    indexWriter.close();
    long endTime = new Date().getTime();

    System.out.println(&quot;MergeFactor: &quot; + indexWriter.mergeFactor);
    System.out.println(&quot;MinMergeDocs: &quot; + indexWriter.minMergeDocs);
    System.out.println(&quot;MaxMergeDocs: &quot; + indexWriter.maxMergeDocs);
    System.out.println(&quot;Document number: &quot; + textFiles.length);
    System.out.println(&quot;Time consumed: &quot; + (endTime - startTime) + &quot; milliseconds&quot;);
  }
}
</pre>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>通过这个例子，我们注意到在调整缓冲区的大小以及写磁盘的频率上面 Lucene 给我们提供了非常大的灵活性。现在我们来看一下代码中的关键语句。如下的代码首先创建了类 IndexWriter 的一个实例，然后对它的三个参数进行赋值。</p>
<p>&nbsp;</p>
<table cellspacing="0" border="0" width="100%" cellpadding="0">
<tbody>
<tr>
<td class="code-outline">
<pre class="displaycode">int mergeFactor = 10;
int minMergeDocs = 10;
int maxMergeDocs = Integer.MAX_VALUE;
IndexWriter indexWriter = new IndexWriter(indexDir,luceneAnalyzer,true);        
indexWriter.mergeFactor = mergeFactor;
indexWriter.minMergeDocs = minMergeDocs;
indexWriter.maxMergeDocs = maxMergeDocs;
</pre>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>下面我们来看一下这三个参数取不同的值对索引时间的影响，注意参数值的不同和索引之间的关系。我们为这个实验准备了 10000 个测试文档。表 1 显示了测试结果。</p>
<p>

<br />
<a name="N10135" title="N10135"></a>
<strong>表1：测试结果</strong>
<br />
<img src="http://www.ibm.com/developerworks/cn/java/wa-lucene/images/table1.gif" border="0" height="199" alt="表1：测试结果" width="502" /></p>
<p>通过表
1，你可以清楚地看到三个参数对索引时间的影响。在实践中，你会经常的改变合并因子和最小合并文档数的值来提高索引性能。只要你有足够大的内存，你可以为
合并因子和最小合并文档数这两个参数赋尽量大的值以提高索引效率，另外我们一般无需更改最大合并文档数这个参数的值，因为系统已经默认将它设置成了最大。</p>
<p>&nbsp;</p>
<table cellspacing="0" border="0" width="100%" cellpadding="0">
<tbody>
<tr>
<td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" alt="" width="100%" />
<br />
<img src="http://www.ibm.com/i/c.gif" border="0" height="6" alt="" width="8" />
</td>
</tr>
</tbody>
</table>
<table class="no-print" cellspacing="0" border="0" align="right" cellpadding="0">
<tbody>
<tr align="right">
<td><img src="http://www.ibm.com/i/c.gif" height="4" alt="" width="100%" />
<br />
<table cellspacing="0" border="0" cellpadding="0">
<tbody>
<tr>
<td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" alt="" width="16" />
<br />
</td>
<td align="right" valign="top"><a href="http://www.ibm.com/developerworks/cn/java/wa-lucene/index.html#main" class="fbox"><strong>回页首</strong>
</a>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p><br /></p>
<p><a name="N10148" title="N10148"></a>
<span class="atitle">Lucene 索引文件结构分析</span>
</p>
<p>在分析 Lucene 的索引文件结构之前，我们先要理解反向索引（Inverted
index）这个概念，反向索引是一种以索引项为中心来组织文档的方式，每个索引项指向一个文档序列，这个序列中的文档都包含该索引项。相反，在正向索引
中，文档占据了中心的位置，每个文档指向了一个它所包含的索引项的序列。你可以利用反向索引轻松的找到那些文档包含了特定的索引项。Lucene正是使用
了反向索引作为其基本的索引结构。</p>
<p>&nbsp;</p>
<table cellspacing="0" border="0" width="100%" cellpadding="0">
<tbody>
<tr>
<td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" alt="" width="100%" />
<br />
<img src="http://www.ibm.com/i/c.gif" border="0" height="6" alt="" width="8" />
</td>
</tr>
</tbody>
</table>
<table class="no-print" cellspacing="0" border="0" align="right" cellpadding="0">
<tbody>
<tr align="right">
<td><img src="http://www.ibm.com/i/c.gif" height="4" alt="" width="100%" />
<br />
<table cellspacing="0" border="0" cellpadding="0">
<tbody>
<tr>
<td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" alt="" width="16" />
<br />
</td>
<td align="right" valign="top"><a href="http://www.ibm.com/developerworks/cn/java/wa-lucene/index.html#main" class="fbox"><strong>回页首</strong>
</a>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p><br /></p>
<p><a name="N10151" title="N10151"></a>
<span class="atitle">索引文件的逻辑视图</span>
</p>
<p> 在Lucene 中有索引块的概念，每个索引块包含了一定数目的文档。我们能够对单独的索引块进行检索。图 2 显示了 Lucene 索引结构的逻辑视图。索引块的个数由索引的文档的总数以及每个索引块所能包含的最大文档数来决定。</p>
<p>

<br />
<a name="N1015C" title="N1015C"></a>
<strong>图2：索引文件的逻辑视图</strong>
<br />
<img src="http://www.ibm.com/developerworks/cn/java/wa-lucene/images/image004.jpg" border="0" height="415" alt="图2：索引文件的逻辑视图" width="467" />
<br /></p>
<table cellspacing="0" border="0" width="100%" cellpadding="0">
<tbody>
<tr>
<td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" alt="" width="100%" />
<br />
<img src="http://www.ibm.com/i/c.gif" border="0" height="6" alt="" width="8" />
</td>
</tr>
</tbody>
</table>
<table class="no-print" cellspacing="0" border="0" align="right" cellpadding="0">
<tbody>
<tr align="right">
<td><img src="http://www.ibm.com/i/c.gif" height="4" alt="" width="100%" />
<br />
<table cellspacing="0" border="0" cellpadding="0">
<tbody>
<tr>
<td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" alt="" width="16" />
<br />
</td>
<td align="right" valign="top"><a href="http://www.ibm.com/developerworks/cn/java/wa-lucene/index.html#main" class="fbox"><strong>回页首</strong>
</a>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p><br /></p>
<p><a name="N1016C" title="N1016C"></a>
<span class="atitle">Lucene 中的关键索引文件</span>
</p>
<p>下面的部分将会分析Lucene中的主要的索引文件，可能分析有些索引文件的时候没有包含文件的所有的字段，但不会影响到对索引文件的理解。</p>
<p>1．索引块文件</p>
<p>这个文件包含了索引中的索引块信息，这个文件包含了每个索引块的名字以及大小等信息。表 2 显示了这个文件的结构信息。</p>
<p>

<br />
<a name="N1017D" title="N1017D"></a>
<strong>表2：索引块文件结构</strong>
<br />
<img src="http://www.ibm.com/developerworks/cn/java/wa-lucene/images/table2.gif" border="0" height="198" alt="表2：索引块文件结构" width="568" /></p>
<p>2．域信息文件</p>
<p>我们知道，索引中的文档由一个或者多个域组成，这个文件包含了每个索引块中的域的信息。表 3 显示了这个文件的结构。</p>
<p>

<br />
<a name="N10195" title="N10195"></a>
<strong>表3：域信息文件结构</strong>
<br />
<img src="http://www.ibm.com/developerworks/cn/java/wa-lucene/images/table3.gif" border="0" height="179" alt="表3：域信息文件结构" width="567" /></p>
<p>3．索引项信息文件</p>
<p>这是索引文件里面最核心的一个文件，它存储了所有的索引项的值以及相关信息，并且以索引项来排序。表 4 显示了这个文件的结构。</p>
<p>

<br />
<a name="N101AD" title="N101AD"></a>
<strong>表4：索引项信息文件结构</strong>
<br />
<img src="http://www.ibm.com/developerworks/cn/java/wa-lucene/images/table4.gif" border="0" height="252" alt="表4：索引项信息文件结构" width="568" /></p>
<p>4．频率文件</p>
<p>这个文件包含了包含索引项的文档的列表，以及索引项在每个文档中出现的频率信息。如果Lucene在索引项信息文件中发现有索引项和搜索词相匹配。
那么 Lucene 就会在频率文件中找有哪些文件包含了该索引项。表5显示了这个文件的一个大致的结构，并没有包含这个文件的所有字段。</p>
<p>

<br />
<a name="N101C5" title="N101C5"></a>
<strong>表5：频率文件的结构</strong>
<br />
<img src="http://www.ibm.com/developerworks/cn/java/wa-lucene/images/table5.gif" border="0" height="124" alt="表5：频率文件的结构" width="567" /></p>
<p>5．位置文件</p>
<p>这个文件包含了索引项在每个文档中出现的位置信息，你可以利用这些信息来参与对索引结果的排序。表 6 显示了这个文件的结构</p>
<p>

<br />
<a name="N101DD" title="N101DD"></a>
<strong>表6：位置文件的结构</strong>
<br />
<img src="http://www.ibm.com/developerworks/cn/java/wa-lucene/images/table6.gif" border="0" height="69" alt="表6：位置文件的结构" width="568" /></p>
<p>到目前为止我们介绍了 Lucene 中的主要的索引文件结构，希望能对你理解 Lucene 的物理的存储结构有所帮助。</p>
          <br/>
          <span style="color:red;">
            <a href="http://longdick.javaeye.com/blog/169116#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 07 Mar 2008 17:03:27 +0800</pubDate>
        <link>http://longdick.javaeye.com/blog/169116</link>
        <guid>http://longdick.javaeye.com/blog/169116</guid>
      </item>
  </channel>
</rss>