Lucene.Net 与 盘古分词

2021-06-29 21:05

阅读:462

using System; using System.IO; using System.Collections.Generic; using System.Linq; using System.Text; using Lucene.Net.Analysis; using Lucene.Net.Documents; using Lucene.Net.Index; using Lucene.Net.Search; using Lucene.Net.Store; using Lucene.Net.Analysis.PanGu; using Maticsoft.DBUtility; using System.Data; using System.Diagnostics; namespace SearchSentence { class Program { public static string[] SplitWords(string content) { List strList = new List(); Analyzer analyzer = new PanGuAnalyzer();//指定使用盘古 PanGuAnalyzer 分词算法 TokenStream tokenStream = analyzer.TokenStream("", new StringReader(content)); Lucene.Net.Analysis.Token token = null; while ((token = tokenStream.Next()) != null) { //Next继续分词 直至返回null strList.Add(token.TermText()); //得到分词后结果 } return strList.ToArray(); } public static void CreateIndex(string strDirectory) { FSDirectory directory = FSDirectory.Open(new DirectoryInfo(strDirectory), new NativeFSLockFactory()); //IndexReader:对索引库进行读取的类 bool isExist = IndexReader.IndexExists(directory); //是否存在索引库文件夹以及索引库特征文件 if (isExist) { //假设索引文件夹被锁定(比方索引过程中程序异常退出或还有一进程在操作索引库)。则解锁 //Q:存在问题 假设一个用户正在对索引库写操作 此时是上锁的 而还有一个用户过来操作时 将锁解开了 于是产生冲突 --解决方法兴许 if (IndexWriter.IsLocked(directory)) { IndexWriter.Unlock(directory); } } //创建向索引库写操作对象 IndexWriter(索引文件夹,指定使用盘古分词进行切词,最大写入长度限制) //补充:使用IndexWriter打开directory时会自己主动对索引库文件上锁 IndexWriter writer = new IndexWriter(directory, new PanGuAnalyzer(), !isExist, IndexWriter.MaxFieldLength.UNLIMITED); DataSet ds = DbHelperSQL.Query("select * from dbo.Sentences", 100); DataTable dt = ds.Tables[0]; int rowsCount = dt.Rows.Count; for (int n = 0; n { if (dt.Rows[n]["Id"].ToString() != "" && dt.Rows[n]["TextZh"].ToString() != "") { //--------------------------------遍历数据源 将数据转换成为文档对象 存入索引库 Document document = new Document(); //new一篇文档对象 --一条记录相应索引库中的一个文档 //向文档中加入字段 Add(字段,值,是否保存字段原始值,是否针对该列创建索引) document.Add(new Field("id", dt.Rows[n]["Id"].ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));//--全部字段的值都将以字符串类型保存 由于索引库仅仅存储字符串类型数据 //Field.Store:表示是否保存字段原值。

指定Field.Store.YES的字段在检索时才干用document.Get取出原值 //Field.Index.NOT_ANALYZED:指定不依照分词后的结果保存--是否按分词后结果保存取决于是否对该列内容进行模糊查询 document.Add(new Field("TextZh", dt.Rows[n]["TextZh"].ToString(), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); //Field.Index.ANALYZED:指定文章内容依照分词后结果保存 否则无法实现兴许的模糊查询 //WITH_POSITIONS_OFFSETS:指示不仅保存切割后的词 还保存词之间的距离 //document.Add(new Field("content", "我常常出去玩", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); writer.AddDocument(document); //文档写入索引库 Console.Write("{0}\r", n+1); } } writer.Close();//会自己主动解锁 directory.Close(); //不要忘了Close,否则索引结果搜不到 } public static void Query(string strQuery) { Stopwatch sw = new Stopwatch(); sw.Start(); FSDirectory directory = FSDirectory.Open(new DirectoryInfo("CH-EG"), new NoLockFactory()); IndexReader reader = IndexReader.Open(directory, true); IndexSearcher searcher = new IndexSearcher(reader); //搜索条件 PhraseQuery query = new PhraseQuery(); //把用户输入的关键字进行分词 foreach(string word in SplitWords(strQuery)) { query.Add(new Term("TextZh", word)); } //query.Add(new Term("content", "C#"));//多个查询条件时 为且的关系 query.SetSlop(100); //指定关键词相隔最大距离 //TopScoreDocCollector盛放查询结果的容器 TopScoreDocCollector collector = TopScoreDocCollector.create(1000, true); searcher.Search(query, null, collector);//依据query查询条件进行查询,查询结果放入collector容器 sw.Stop(); //TopDocs 指定0到GetTotalHits() 即全部查询结果中的文档 假设TopDocs(20,10)则意味着获取第20-30之间文档内容 达到分页的效果 ScoreDoc[] docs = collector.TopDocs(0, collector.GetTotalHits()).scoreDocs; //展示数据实体对象集合 for (int i = 0; i { int docId = docs[i].doc;//得到查询结果文档的id(Lucene内部分配的id) Document doc = searcher.Doc(docId);//依据文档id来获得文档对象Document Console.Write("{0}\n", doc.Get("TextZh")); } TimeSpan ts2 = sw.Elapsed; Console.WriteLine("本次查询总共花费{0}ms.\n", ts2.TotalMilliseconds); } static void Main(string[] args) { //CreateIndex("CH-EG"); Console.Write("Press phrase: \n"); string strQuery = Console.ReadLine(); while (strQuery != "") { Query(strQuery); Console.Write("Press phrase: \n"); strQuery = Console.ReadLine(); } } } }


评论


亲,登录后才可以留言!