问题描述
谈之前先听我啰嗦两句~亲。我秉承了自己一贯作风~拿来主义。当领导对我说:下个项目WEB前端用索引Lucene.Net+盘古分词和XML,完全脱离数据库。听到这些两眼一抹黑,咋办压根连听都很少听到过啊!万念俱灰的感觉,为了金钱只能咬牙切齿蹦出来两个字:拼了。毕竟在我很遥远时代听过,看过感觉太复杂永远也用不到丢弃了。没想到这次“美梦”成真了。只能依靠万能的百度CSDN博客园,拼命找啊。找了好多,不是版本太低,就是我水平不够,理解不透,好吧菜鸟只是水平下等,大虾们原谅。通过种种把终于开始第一个DEMO,没办法只能,时间就是金钱~我的朋友(摘WOW)。就从我亲身体验开始啊,希望大家一起探讨,不带人身攻击的提前声明:可以拍砖~探讨~我是带着学习的心态来和大虾们学习的!不罗嗦了,先开始第一部分:创建索引和增删改索引Lucene.Net版本用的2.9。。。。。。PanGu盘古用的2.3,下载地址:下载后怎么引用就不说了,如果不会~自宫算了o(∩_∩)o哈哈使用盘古分词钱别忘记~加载盘古引用路径://定义盘古分词的xml引用路径PanGu.Segment.Init(PanGuXmlPath);/*------------------==============创建索引开始=============---------------*////<summary>///创建索引生成///</summary>privatevoidCreateIndex(){IndexWriterwriter=null;try{//创建索引目录if(!Directory.Exists(IndexDic))//配置文件放最后亲{Directory.CreateDirectory(IndexDic);}/*注释掉的是数据库抓取的数据循环的,带着学习心态的同志们,请自行读取,这里辛苦你们了*///从数据库获取数据//DataTabledt=NULL;//IndexWriter第三个参数:true指重新创建索引,false指从当前索引追加....此处为新建索引所以为---true。这里用的盘古分词writer=newIndexWriter(IndexDic,PanGuAnalyzer,true,Lucene.Net.Index.IndexWriter.MaxFieldLength.LIMITED);//if(dt.Rows.Count>0)//{//for(inti=0;i<dt.Rows.Count;i++)//{#region数据库读取数据赋值给自定义值stringNo="NO12345";stringName="数据库读取的亲们";stringPrice="0.00";//if(!string.IsNullOrEmpty(Price))//{//Price="1.11";//}#endregion#region赋值并生成索引Documentdoc=newDocument();//只做存储~不分词doc.Add(newField("No",No,Field.Store.YES,Field.Index.NOT_ANALYZED));//名字进行分词doc.Add(newField("Name",Name,Field.Store.YES,Field.Index.ANALYZED));//方便排序,根据价格区间排序前需要把参数具体化,我百度出的自我感觉最好办法,如有更好请告知谢谢FieldablePriceValue=newNumericField("Price",Field.Store.YES,true);((NumericField)PriceValue).SetFloatValue(float.Parse(Price));doc.Add(PriceValue);#endregion//执行添加索引writer.AddDocument(doc);//}//}//索引重排writer.Optimize();writer.Close();}catch{//出错也不要忘记关闭writer.Close();}}///<summary>///引存放目录///</summary>protectedstringIndexDic{get{returnServer.MapPath("/NewIndexDic/Seach");}}///<summary>///盘古分词器///</summary>protectedAnalyzerPanGuAnalyzer{get{returnnewPanGuAnalyzer();}}///<summary>///盘古分词的配置文件///</summary>protectedstringPanGuXmlPath{get{returnServer.MapPath("/PanGu/PanGu.xml");}}修改删除增加,明天继续~洗澡
解决方案
本帖最后由 u012076966 于 2013-09-10 22:01:03 编辑
解决方案二:
有错别字,见谅,语文不及格
解决方案三:
第一次分享发帖可能有些混乱~
解决方案四:
感谢你的分享啊。如果没有人回复,你是可以自己编辑的。
解决方案五:
多谢分享呀,虽然还没用过,不过,看了挺有触发的
解决方案六:
引用3楼caozhy的回复:
感谢你的分享啊。如果没有人回复,你是可以自己编辑的。
3Q
解决方案七:
整理下思路,开始增删改,其实也不复杂,只是说下搜索出来的资料整理下而已,
解决方案八:
增加、修改、删除和创建基本一样,需要注意的是://第三个参数要为:false,我注释里面也有些,如果仔细看writer=newIndexWriter(IndexDic,PanGuAnalyzer,false,Lucene.Net.Index.IndexWriter.MaxFieldLength.LIMITED);/*第二个注意是调用函数不一样我分别写出来*///添加一条新的索引writer.AddDocument(doc);//修改一条索引Termterm=newTerm("No",No);writer.UpdateDocument(term,doc);//删除一条索引Termterm=newTerm("No",No);writer.DeleteDocuments(term);看了是不是挺简单,接下来就是查询了
解决方案:
生成索引是比较麻烦的。我原来那个用的是ShootAnalyzer的分词,每周生成一次索引(要不然有的新的关键词原分词系统里面没有的就检索不到)。
解决方案:
当时大概几个G的HTML静态文件(具体多少G记不清了),生成索引以后大概在700M左右。
解决方案:
引用8楼5653325的回复:
生成索引是比较麻烦的。我原来那个用的是ShootAnalyzer的分词,每周生成一次索引(要不然有的新的关键词原分词系统里面没有的就检索不到)。
是啊,不过自带分词我感觉最好用的就是:SimpleAnalyzer()可以按标点符号分词,这样对我前端属性搜索非常便利,盘古分词真心不行,不知道大侠们有办法没(比如:无线上网,停车位,外送),盘古分词可以按标点符号分词最好了
解决方案:
忘记增加了一个索引字段://当WEB前端搜索显示全部索引库数据时候,我网上找资料好像没有很的好解决方案,都是在做索引的时候增加一个特殊字段索引或其他,我就是利用增加一个特殊字段索引,当用户搜索显示全部数据时候,传入参数:alllist就能查询出所有索引库数据,如果有更好办法请告知下,这里先谢了。doc.Add(newField("AllList","alllist",Field.Store.YES,Field.Index.NOT_ANALYZED));
解决方案:
引用10楼u012076966的回复:
Quote: 引用8楼5653325的回复:
生成索引是比较麻烦的。我原来那个用的是ShootAnalyzer的分词,每周生成一次索引(要不然有的新的关键词原分词系统里面没有的就检索不到)。是啊,不过自带分词我感觉最好用的就是:SimpleAnalyzer()可以按标点符号分词,这样对我前端属性搜索非常便利,盘古分词真心不行,不知道大侠们有办法没(比如:无线上网,停车位,外送),盘古分词可以按标点符号分词最好了
我当时那个是针对静态HTML文件做的全文检索。当时有HTML、分词库、索引库、索引建立更新程序(winform)、搜索功能(webform)组成,基本没涉及到数据库。流程是先用winform读取分词库来给所有的html建立索引库,然后搜索的时候根据用户传递过来的关键字返回符合关键字的html的url路径。所以这个分词库需要每周更新(没法做到那么智能,会自动区分关键字),每周更新索引。更新索引的时间比较长(4-6G大概需要4个小时左右(单线程))。我这方法是最笨的方法,当时也是百度不到文档,自己扣出来的。最终总算是实现了。不过现在像百度和google都带的有站内搜索,用着还是比较方便的。引用一个js就行了。
解决方案:
分享一些简单lucene.net属性说明整理了下,很简单,凭着分享精神不收积分,哈哈。顺带附上了盘古分词的维护工具
解决方案:
感谢分享
解决方案:
慢慢来,整理下工作,交接辞职
解决方案:
菜鸟一枚路过,收藏了,以后“美梦”成真时说不定用得上!
解决方案:
引用16楼yw39019724的回复:
菜鸟一枚路过,收藏了,以后“美梦”成真时说不定用得上!
解决方案:
楼主好人啊,这个lucene现在不开源了吧。
解决方案:
测试下,可以回复了不
解决方案:
/*----------------===============简单搜索============---------------*////<summary>///加载绑定数据///</summary>protectedvoidBind(){stringName=txtName.Text;stringAlllist="1";//URL传值//价格区间查询stringPriceStart=txtStart.Text;stringPriceEnd=txtEnd.Text;Hitsmyhit=null;//IndexDic索引配置文件,上面已发IndexSearchermysea=newIndexSearcher(IndexDic);//SortField构造函数第三个字段true为降序,false为升序stringstrListDesc=ddlOrder.SelectedValue;//排序字段Sortsort=null;//排序字段priceif(strListDesc=="1"){sort=newSort(newSortField("price",SortField.AUTO,false));}else{sort=newSort(newSortField("price",SortField.AUTO,true));}BooleanQuerybooleanQuery=newBooleanQuery();TermQuerytermNO=null;TermQuerytermAllList=null;//查询所有if(Alllist=="1"){termAllList=newTermQuery(newTerm("AllList","alllist"));booleanQuery.Add(termAllList,BooleanClause.Occur.MUST);}//按盘古分词查询if(Name!=""){Name=GetKeyWordsSplitBySpace(Name);QueryParserparse=newQueryParser("Name",PanGuAnalyzer);Queryquery=parse.Parse(Name);parse.SetDefaultOperator(QueryParser.Operator.OR);booleanQuery.Add(query,BooleanClause.Occur.MUST);}Filterfilter=null;//价格区间查询if(PriceStart!=""&&PriceEnd!=""){floatfspc=float.Parse(PriceStart);floatfepc=float.Parse(PriceEnd);booleanQuery.Add(NumericRangeQuery.NewFloatRange("Price",fspc,fepc,true,true),BooleanClause.Occur.MUST);}//分页我使用的是第三方分页控件TopDocsdocs=mysea.Search(booleanQuery,filter,AspNetPager1.StartRecordIndex+AspNetPager1.PageSize-1,sort);AspNetPager1.RecordCount=docs.totalHits;if(docs!=null&&docs.totalHits>0){DataRowmyrow;DataTablemytab=newDataTable();mytab.Columns.Add("No");mytab.Columns.Add("Name");mytab.Columns.Add("Price1");mytab.Clear();for(inti=0;i<docs.totalHits;i++){//分页读取数据if(i>=AspNetPager1.StartRecordIndex-1&&i<AspNetPager1.StartRecordIndex+AspNetPager1.PageSize-1){Documentdoc=mysea.Doc(docs.scoreDocs[i].doc);myrow=mytab.NewRow();#region给DataTable每行赋值根据DataRowmyrow[0]=doc.Get("No").ToString();myrow[1]=doc.Get("Name").ToString();myrow[2]=doc.Get("Price1").ToString();#endregionmytab.Rows.Add(myrow);myrow.AcceptChanges();}}//绑定数据控件rp_Item.DataSource=mytab;rp_Item.DataBind();mysea.Close();}}///<summary>///处理关键字为索引格式///</summary>///<paramname="keywords"></param>///<returns></returns>privatestringGetKeyWordsSplitBySpace(stringkeywords){PanGuTokenizerktTokenizer=newPanGuTokenizer();StringBuilderresult=newStringBuilder();ICollection<WordInfo>words=ktTokenizer.SegmentToWordInfos(keywords);foreach(WordInfowordinwords){if(word==null){continue;}result.AppendFormat("{0}^{1}.0",word.Word,(int)Math.Pow(3,word.Rank));}returnresult.ToString().Trim();}
解决方案:
感谢分享,建议写到个人的blog里面
解决方案:
简单把,基本上结束了。有空整理个小DEMO,其实好多也是我拿别人的,直接用的,这里谢谢那些大虾们
解决方案:
引用21楼nice_fish的回复:
感谢分享,建议写到个人的blog里面
不错建议,我去看看嘿嘿
解决方案:
LZ,你好啊!我用的也是盘古分词,但是搜索有些单个字的时候查出来的数据不完整,您能帮我分析一下吗?QQ:237377144,谢谢LZ