Lucene.Net

来源:互联网 发布:手机上c语言编程软件 编辑:程序博客网 时间:2024/05/16 10:02

        /// <summary>
        /// 在HttpApplication 类的第一个实例被创建时,该事件被触发它允许你创建可以由所有HttpApplication 实例访问的对象
        /// </summary>
        protected void Application_Start(object sender, EventArgs e)
        {

            //开启全文检索功能 分词库配置文件需要放置在 bin文件夹中
            KSWECDS.Web.LuneceManager.IndexManager.OIndexManager.StartNewThread();
        }



using System;

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Web;
using KSWECDS.Web.Models;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Search;
using Lucene.Net.Store;
using PanGu;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.PanGu;
using Lucene.Net.QueryParsers;
using System.Diagnostics;


namespace KSWECDS.Web
{
    public class LuneceManager
    {
        public class IndexManager
        {
            public static readonly IndexManager OIndexManager = new IndexManager();
            //索引文档保存位置   
            public static readonly string indexPath = HttpContext.Current.Server.MapPath("~/Lucene.Net/IndexData");
            //当前程序集
            private static System.Reflection.Assembly Assembly = KSWECDS.Web.Extensions.Common.Assembly;
            //索引类的 公共属性
            private static PropertyInfo[] LuceneModelProtyInfos = typeof(LuneceModel).GetProperties();


            /// <summary>
            /// 开启全文检索
            /// </summary>
            private static bool OpenLuncene
            {
                get
                {
                    bool OpenLuncene = false;
                    string OpenLunceneStr = System.Configuration.ConfigurationManager.AppSettings["OpenLuncene"] ?? "";
                    if (!string.IsNullOrEmpty(OpenLunceneStr))
                    {
                        if (OpenLunceneStr.Trim().ToLower() == "true")
                            OpenLuncene = true;
                    }
                    return OpenLuncene;
                }
            }


            //自动设置值
            public static List<string> SetLuceneAutoNames = new List<string>() { 
                "ADDWHO",
                "ADDTS",
                "EDITWHO",
                "EDITTS",
                "OperatingPoint"
            };
            //设置全文检索的表 
            public static List<string> AutoLunceneTable = new List<string> { 
                "VIP_CDARETURNXML",
                "VIPRETURNMQ",
                "CDARETURNMQ",
                "CQZGRETURNMQ",
                "CQZGDECRETURNMQ",
                "CQZGSHRETURNMQ",
                "TMLOCKJSON",
                "MQAUTOSENDXML",
                "MESSAGE"
            };


            /// <summary>
            /// 错误日志 文件夹名称
            /// </summary>
            private string LuneceErrorDir
            {
                get
                {
                    var LEDir = System.Configuration.ConfigurationManager.AppSettings["LuneceErrorDir"] ?? "LuneceErrorDir";
                    return LEDir;
                }
            }


            private IndexManager()
            {
            }


            //请求队列 解决索引目录同时操作的并发问题
            private Queue<LuneceModel> LuneceModelQueue = new Queue<LuneceModel>();


            /// <summary>
            /// 加入队列
            /// </summary>
            /// <param name="entity"></param>
            /// <param name="_entityProptys"></param>
            /// <param name="OLuneceIndexType"></param>
            private void EnqueueLuceneModel(object entity, PropertyInfo[] _entityProptys, LuneceIndexType OLuneceIndexType)
            {
                if (!OpenLuncene)
                    return;
                if (!AutoLunceneTable.Any(n => entity.GetType().ToString().ToUpper().EndsWith(n)))
                    return;


                LuneceModel OLuneceModel = new LuneceModel();
                try
                {
                    OLuneceModel.TableName = entity.GetType().ToString();
                    OLuneceModel.TableKey = GetKeyValue(entity, _entityProptys);
                    OLuneceModel.IndexType = OLuneceIndexType;
                    OLuneceModel.Content = GetStrinValue(entity, _entityProptys);


                    var WhereLuceneModelProtyInfos = LuceneModelProtyInfos.Where(x => SetLuceneAutoNames.Any(n => n == x.Name.ToUpper()));
                    foreach (var item in WhereLuceneModelProtyInfos)
                    {
                        var Where_entityProptys = _entityProptys.Where(x => x.Name.ToUpper() == item.Name);
                        if (Where_entityProptys.Any())
                        {
                            var objValue = Where_entityProptys.FirstOrDefault().GetValue(entity);
                            if (objValue != null)
                            {
                                item.SetValue(OLuneceModel, objValue);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    string ErrMsg = KSWECDS.Web.Extensions.Common.GetExceptionMsg(ex);
                    if (!(string.IsNullOrEmpty(OLuneceModel.TableName) || string.IsNullOrEmpty(OLuneceModel.TableKey) || string.IsNullOrEmpty(OLuneceModel.Content)))
                        SQLDALHelper.WriteLogHelper.WriteLog(ErrMsg + "-" + Newtonsoft.Json.JsonConvert.SerializeObject(OLuneceModel), LuneceErrorDir, true);
                    return;
                }
                if (!(string.IsNullOrEmpty(OLuneceModel.TableName) || string.IsNullOrEmpty(OLuneceModel.TableKey) || string.IsNullOrEmpty(OLuneceModel.Content)))
                    LuneceModelQueue.Enqueue(OLuneceModel);
            }


            /// <summary>
            /// 添加索引请求至队列
            /// </summary>
            /// <param name="books"></param>
            public void LuneceInsert(object entity, PropertyInfo[] _entityProptys)
            {
                EnqueueLuceneModel(entity, _entityProptys, LuneceIndexType.Insert);
            }


            /// <summary>
            /// 删除索引请求至队列
            /// </summary>
            /// <param name="bid"></param>
            public void LuneceDelete(object entity, PropertyInfo[] _entityProptys)
            {
                EnqueueLuceneModel(entity, _entityProptys, LuneceIndexType.Delete);
            }


            /// <summary>
            /// 添加修改索引(实质上是先删除原有索引 再新增修改后索引)请求至队列
            /// </summary>
            /// <param name="books"></param>
            public void LuneceModify(object entity, PropertyInfo[] _entityProptys)
            {
                EnqueueLuceneModel(entity, _entityProptys, LuneceIndexType.Modify);
            }


            public void StartNewThread()
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(QueueToIndex));
            }


            //定义一个线程 将队列中的数据取出来 插入索引库中
            private void QueueToIndex(object para)
            {
                while (true)
                {
                    if (LuneceModelQueue.Count > 0)
                    {
                        try
                        {
                            UpdateLunceneIndex();
                        }
                        catch (Exception ex)
                        {
                            SQLDALHelper.WriteLogHelper.WriteLog("全文检索错误(线程):" + KSWECDS.Web.Extensions.Common.GetExceptionMsg(ex), LuneceErrorDir, true);
                        }
                    }
                    else
                    {
                        Thread.Sleep(1000);
                    }
                }
            }


            /// <summary>
            /// 获取索引添加器
            /// </summary>
            /// <returns></returns>
            public IndexWriter GetIndexWriter(FSDirectory directory)
            {
                //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);


                return writer;
            }


            /// <summary>
            /// 添加索引
            /// </summary>
            /// <param name="writer"></param>
            /// <param name="OLuneceModel"></param>
            private void IndexAddDocument(IndexWriter writer, LuneceModel OLuneceModel)
            {
                if (OLuneceModel.IndexType == LuneceIndexType.Modify)
                {
                    //先删除 再新增
                    IndexDeleteDocuments(writer, OLuneceModel);
                }
                Document document = new Document();
                try
                {
                    //Field.Store:表示是否保存字段原值。指定Field.Store.YES的字段在检索时才能用document.Get取出原值  
                    //Field.Index.NOT_ANALYZED:指定不按照分词后的结果保存--是否按分词后结果保存取决于是否对该列内容进行模糊查询
                    document.Add(new Field("TableName", OLuneceModel.TableName ?? "", Field.Store.YES, Field.Index.NOT_ANALYZED));
                    document.Add(new Field("TableKey", OLuneceModel.TableKey ?? "", Field.Store.YES, Field.Index.NOT_ANALYZED));
                    //Field.Index.ANALYZED:指定文章内容按照分词后结果保存 否则无法实现后续的模糊查询 
                    //WITH_POSITIONS_OFFSETS:指示不仅保存分割后的词 还保存词之间的距离
                    document.Add(new Field("Content", OLuneceModel.Content ?? "", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
                    document.Add(new Field("ADDWHO", OLuneceModel.ADDWHO ?? "", Field.Store.YES, Field.Index.NOT_ANALYZED));
                    document.Add(new Field("ADDTS", (OLuneceModel.ADDTS == null ? "" : Convert.ToDateTime(OLuneceModel.ADDTS).ToString("yyyy-MM-dd")), Field.Store.YES, Field.Index.NOT_ANALYZED));
                    document.Add(new Field("EDITWHO", OLuneceModel.EDITWHO ?? "", Field.Store.YES, Field.Index.NOT_ANALYZED));
                    document.Add(new Field("EDITTS", (OLuneceModel.EDITTS == null ? "" : Convert.ToDateTime(OLuneceModel.EDITTS).ToString("yyyy-MM-dd")), Field.Store.YES, Field.Index.NOT_ANALYZED));
                    document.Add(new Field("OperatingPoint", OLuneceModel.OperatingPoint <= 0 ? "" : OLuneceModel.OperatingPoint.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
                    writer.AddDocument(document);
                }
                catch (Exception ex)
                {
                    SQLDALHelper.WriteLogHelper.WriteLog("创建索引出错:" + KSWECDS.Web.Extensions.Common.GetExceptionMsg(ex), LuneceErrorDir, true);
                    writer.Close();
                    Thread.Sleep(10);
                    FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NativeFSLockFactory());
                    writer = GetIndexWriter(directory);
                }
            }


            /// <summary>
            /// 删除索引
            /// </summary>
            /// <param name="writer"></param>
            /// <param name="OLuneceModel"></param>
            private void IndexDeleteDocuments(IndexWriter writer, LuneceModel OLuneceModel)
            {
                writer.DeleteDocuments(new Term[]{ 
                            new Term("TableName", OLuneceModel.TableName), 
                            new Term("TableKey", OLuneceModel.TableKey),
                            new Term("OperatingPoint", OLuneceModel.OperatingPoint.ToString())
                        });
            }


            /// <summary>
            /// 更新索引库操作
            /// </summary>
            private void UpdateLunceneIndex()
            {
                FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NativeFSLockFactory());
                //创建向索引库写操作对象  IndexWriter(索引目录,指定使用盘古分词进行切词,最大写入长度限制)
                //补充:使用IndexWriter打开directory时会自动对索引库文件上锁
                IndexWriter writer = GetIndexWriter(directory);


                while (LuneceModelQueue.Count > 0)
                {
                    LuneceModel OLuneceModel = LuneceModelQueue.Dequeue();
                    if (OLuneceModel.IndexType == LuneceIndexType.Delete)
                    {
                        IndexDeleteDocuments(writer, OLuneceModel);
                    }
                    else
                    {
                        IndexAddDocument(writer, OLuneceModel);
                    }
                }


                writer.Close();
                directory.Close();
            }


            #region 反射获取索引所需数据集


            //合并string格式全文检索 最小长度
            private int StringMaxLength = 51;


            /// <summary>
            /// 获取
            /// </summary>
            /// <returns></returns>
            private string GetKeyValue(object entity, PropertyInfo[] _entityProptys)
            {
                string KeyVal = "";
                foreach (var propinfo in _entityProptys)
                {
                    var ArrKeyAttr = propinfo.GetCustomAttributes(typeof(KeyAttribute), false);
                    if (ArrKeyAttr.Any())
                    {
                        KeyVal = propinfo.GetValue(entity).ToString();
                        break;
                    }
                }
                if (string.IsNullOrEmpty(KeyVal))
                {
                    var KeyProptyS = _entityProptys.Where(x => x.Name.ToLower() == "ID");
                    if (KeyProptyS.Any())
                    {
                        KeyVal = KeyProptyS.FirstOrDefault().GetValue(entity).ToString();
                    }
                }
                return KeyVal;
            }


            /// <summary>
            /// 获取对象所有string字符串
            /// 以,连接
            /// </summary>
            /// <returns></returns>
            private string GetStrinValue(object entity, PropertyInfo[] _entityProptys)
            {
                string StringVal = "";
                foreach (var propinfo in _entityProptys)
                {
                    var propInfoType = propinfo.PropertyType;
                    if (propInfoType == typeof(string) || propInfoType == typeof(String))
                    {
                        if (SetLuceneAutoNames.Any(x => x == propinfo.Name.ToUpper()))
                        {
                            continue;
                        }
                        var ArrMax_StrLenAttr = propinfo.GetCustomAttributes(typeof(StringLengthAttribute), false).Union(propinfo.GetCustomAttributes(typeof(MaxLengthAttribute), false));


                        if (ArrMax_StrLenAttr.Any())
                        {
                            if (ArrMax_StrLenAttr.Any())
                            {
                                var ObjStrLenAttr = ArrMax_StrLenAttr.FirstOrDefault();
                                var OStrLenAttrPropertyS = ObjStrLenAttr.GetProperties();
                                var WhereOStrLenAttrPropertyS = OStrLenAttrPropertyS.Where(x => x.Name == "MaximumLength" || x.Name == "Length");
                                if (WhereOStrLenAttrPropertyS.Any())
                                {
                                    var _MaximumLength = WhereOStrLenAttrPropertyS.FirstOrDefault().GetValue(ObjStrLenAttr);
                                    if (_MaximumLength != null)
                                    {
                                        int MaximumLength = 0;
                                        int.TryParse(_MaximumLength.ToString(), out MaximumLength);
                                        if (MaximumLength > StringMaxLength)
                                        {
                                            var objVal = propinfo.GetValue(entity);
                                            if (objVal != null)
                                                StringVal += (objVal ?? "") + ",";
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            var objVal = propinfo.GetValue(entity);
                            if (objVal != null)
                                StringVal += (objVal ?? "") + ",";
                        }
                    }
                }
                if (!string.IsNullOrEmpty(StringVal))
                {
                    StringVal = StringVal.Substring(0, StringVal.Length - 1);
                }
                return StringVal;
            }


            #endregion


            /// <summary>
            /// 创建索引
            /// </summary>
            public void CreateIndex(LuneceModel OLuneceModel)
            {
                FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NativeFSLockFactory());
                //创建向索引库写操作对象  IndexWriter(索引目录,指定使用盘古分词进行切词,最大写入长度限制)
                //补充:使用IndexWriter打开directory时会自动对索引库文件上锁
                IndexWriter writer = GetIndexWriter(directory);
                IndexAddDocument(writer, OLuneceModel);
                writer.Close();//会自动解锁
                directory.Close(); //不要忘了Close,否则索引结果搜不到
            }


            /// <summary>
            /// 创建索引
            /// </summary>
            public void CreateIndex(List<LuneceModel> ArrLuneceModel)
            {
                FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NativeFSLockFactory());
                //创建向索引库写操作对象  IndexWriter(索引目录,指定使用盘古分词进行切词,最大写入长度限制)
                //补充:使用IndexWriter打开directory时会自动对索引库文件上锁
                IndexWriter writer = GetIndexWriter(directory);


                foreach (var OLuneceModel in ArrLuneceModel)
                {
                    IndexAddDocument(writer, OLuneceModel);
                }


                writer.Close();//会自动解锁
                directory.Close(); //不要忘了Close,否则索引结果搜不到
            }


            /// <summary>
            /// 从索引库中检索关键字
            /// </summary>
            public List<LuneceModel> SearchFromIndexData(string SearchKey, int PageSize = 10, int PageIndex = 1, string TableName = "", string TableKey = "", string OperatingPoint = "")
            {
                FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NoLockFactory());
                IndexReader reader = IndexReader.Open(directory, true);
                IndexSearcher searcher = new IndexSearcher(reader);
                //搜索条件
                BooleanQuery bQuery = new BooleanQuery();
                //1.MUST和MUST:取得连个查询子句的交集。 
                //2.MUST和MUST_NOT:表示查询结果中不能包含MUST_NOT所对应得查询子句的检索结果。 
                //3.SHOULD与MUST_NOT:连用时,功能同MUST和MUST_NOT。 
                //4.SHOULD与MUST连用时,结果为MUST子句的检索结果,但是SHOULD可影响排序。 
                //5.SHOULD与SHOULD:表示“或”关系,最终检索结果为所有检索子句的并集。 
                //6.MUST_NOT和MUST_NOT:无意义,检索无结果。 
                if (!SearchKey.IsNullOrEmpty())
                {
                    #region 方法1


                    ////只能相同的字段
                    //PhraseQuery _query = new PhraseQuery();
                    //string[] ArrSplit_Words = SplitContent.SplitWords(SearchKey);
                    ////把用户输入的关键字进行分词
                    //foreach (string word in ArrSplit_Words)
                    //{
                    //    _query.Add(new Term("Content", word));
                    //}
                    //if (ArrSplit_Words.Any())
                    //    bQuery.Add(_query, BooleanClause.Occur.MUST);
                    //query.SetSlop(100); //指定关键词相隔最大距离


                    #endregion


                    #region 方法2


                    QueryParser parse = new QueryParser("Content", new PanGuAnalyzer());
                    Query _query = parse.Parse(SearchKey);
                    //_query.SetBoost();//设置搜索权重比
                    parse.SetDefaultOperator(QueryParser.Operator.AND);
                    bQuery.Add(_query, BooleanClause.Occur.MUST);


                    #endregion
                }


                if (!string.IsNullOrEmpty(TableName))
                {
                    Term term = new Term("TableName", TableName);
                    Query _query = new TermQuery(term);


                    #region 分词 搜索


                    //QueryParser parse = new QueryParser("TableName", new PanGuAnalyzer());
                    //Query _query = parse.Parse(TableName);
                    //parse.SetDefaultOperator(QueryParser.Operator.AND);


                    #endregion


                    bQuery.Add(_query, BooleanClause.Occur.MUST);
                    //query.Add(new Term("TableName", TableName));
                }
                if (!string.IsNullOrEmpty(TableKey))
                {
                    Term term = new Term("TableKey", TableKey);
                    Query _query = new TermQuery(term);


                    #region 分词 搜索


                    //QueryParser parse = new QueryParser("TableKey", new PanGuAnalyzer());
                    //Query _query = parse.Parse(TableKey);
                    //parse.SetDefaultOperator(QueryParser.Operator.AND);


                    #endregion


                    bQuery.Add(_query, BooleanClause.Occur.MUST);
                    //query.Add(new Term("TableKey", TableKey));
                }
                if (!string.IsNullOrEmpty(OperatingPoint))
                {
                    Term term = new Term("OperatingPoint", OperatingPoint);
                    Query _query = new TermQuery(term);


                    #region 分词 搜索


                    //QueryParser parse = new QueryParser("OperatingPoint", new PanGuAnalyzer());
                    //Query _query = parse.Parse(OperatingPoint);
                    //parse.SetDefaultOperator(QueryParser.Operator.AND);


                    #endregion


                    bQuery.Add(_query, BooleanClause.Occur.MUST);
                    //query.Add(new Term("OperatingPoint", OperatingPoint));
                }


                ScoreDoc[] docs = null;//搜索结果


                #region Lucene搜索


                long lSearchTime = 0;//搜索耗时
                Stopwatch stopwatch = Stopwatch.StartNew();
                var total = 0;
                var skip = PageSize * (PageIndex - 1);
                var take = 0;


                #region 方法1


                //TopScoreDocCollector盛放查询结果的容器
                TopScoreDocCollector collector = TopScoreDocCollector.create(PageSize, true);
                searcher.Search(bQuery, collector);//根据query查询条件进行查询,查询结果放入collector容器
                lSearchTime = stopwatch.ElapsedMilliseconds;
                total = collector.GetTotalHits();
                skip = PageSize * (PageIndex - 1);
                take = (total - skip) > PageSize ? PageSize : (total - skip);
                //TopDocs 指定0到GetTotalHits() 即所有查询结果中的文档 如果TopDocs(20,10)则意味着获取第20-30之间文档内容 达到分页的效果
                docs = collector.TopDocs(skip, take).scoreDocs;


                #endregion


                #region 方法2


                ////SortField构造函数第三个字段true为降序,false为升序
                //Sort sort = new Sort(new SortField("TableKey", SortField.DOC, true));
                //TopDocs _docs = searcher.Search(bQuery, (Filter)null, PageSize * PageIndex, sort);
                //stopwatch.Stop();
                //total = _docs.totalHits;
                //skip = PageSize * (PageIndex - 1);
                //take = (total - skip) > PageSize ? PageSize : (total - skip);
                //if (_docs != null && total > 0)
                //{
                //    lSearchTime = stopwatch.ElapsedMilliseconds;
                //    docs = _docs.scoreDocs;
                //}
                //else
                //    docs = new ScoreDoc[] { };


                #endregion


                #endregion


                //展示数据实体对象集合
                List<LuneceModel> ArrOLuneceModel = new List<LuneceModel>();
                for (int i = 0; i < docs.Length; i++)
                {
                    if (i < take)
                    {
                        int docId = docs[i].doc;//得到查询结果文档的id(Lucene内部分配的id)
                        Document doc = searcher.Doc(docId);//根据文档id来获得文档对象Document


                        LuneceModel OLuneceModel = new LuneceModel();
                        OLuneceModel.TableName = doc.Get("TableName");
                        OLuneceModel.TableKey = doc.Get("TableKey");
                        //搜索关键字高亮显示 使用盘古提供高亮插件
                        OLuneceModel.Content = SplitContent.HightLight(SearchKey, doc.Get("Content"));
                        OLuneceModel.ADDWHO = doc.Get("ADDWHO");
                        OLuneceModel.ADDTS = string.IsNullOrEmpty(doc.Get("ADDTS")) ? null : (DateTime?)Convert.ToDateTime(doc.Get("ADDTS"));
                        OLuneceModel.EDITTS = string.IsNullOrEmpty(doc.Get("EDITTS")) ? null : (DateTime?)Convert.ToDateTime(doc.Get("EDITTS"));
                        OLuneceModel.EDITWHO = doc.Get("EDITWHO");
                        OLuneceModel.OperatingPoint = string.IsNullOrEmpty(doc.Get("EDITTS")) ? 0 : Convert.ToInt32(doc.Get("EDITWHO"));
                        ArrOLuneceModel.Add(OLuneceModel);
                    }
                    else
                        break;
                }
                return ArrOLuneceModel;
            }
        }


        /// <summary>
        /// 分词
        /// </summary>
        public class SplitContent
        {
            public static string[] SplitWords(string content)
            {
                List<string> strList = new List<string>();
                Analyzer analyzer = new PanGuAnalyzer();//指定使用盘古 PanGuAnalyzer 分词算法
                TokenStream tokenStream = analyzer.TokenStream("", new StringReader(content));
                Lucene.Net.Analysis.Token token = null;
                while ((token = tokenStream.Next()) != null)
                {
                    if (token != null)
                    {
                        if (token.TermText() != null)
                        {
                            //Next继续分词 直至返回null
                            strList.Add(token.TermText()); //得到分词后结果
                        }
                    }
                }
                return strList.ToArray();
            }


            //需要添加PanGu.HighLight.dll的引用
            /// <summary>
            /// 搜索结果高亮显示
            /// </summary>
            /// <param name="keyword"> 关键字 </param>
            /// <param name="content"> 搜索结果 </param>
            /// <returns> 高亮后结果 </returns>
            public static string HightLight(string keyword, string content)
            {
                //创建HTMLFormatter,参数为高亮单词的前后缀
                PanGu.HighLight.SimpleHTMLFormatter simpleHTMLFormatter = new PanGu.HighLight.SimpleHTMLFormatter("<font style=\"font-style:normal;color:#cc0000;\"><b>", "</b></font>");
                //创建 Highlighter ,输入HTMLFormatter 和 盘古分词对象Semgent
                PanGu.HighLight.Highlighter highlighter = new PanGu.HighLight.Highlighter(simpleHTMLFormatter, new Segment());
                //设置每个摘要段的字符数
                highlighter.FragmentSize = 1000;
                //获取最匹配的摘要段
                return highlighter.GetBestFragment(keyword, content);
            }
        }
    }


    //操作类型枚举
    public enum LuneceIndexType
    {
        Insert = 0,
        Modify = 1,
        Delete = 2
    }
}


namespace KSWECDS.Web.Models
{
    public class LuneceModel
    {
        [Display(Name = "表名", Description = "", Order = 1)]
        public string TableName { get; set; }


        [Display(Name = "表主键", Description = "", Order = 2)]
        public string TableKey { get; set; }


        //[Display(Name = "标题", Description = "", Order = 3)]
        //public string Title { get; set; }


        //[Display(Name = "副标题", Description = "", Order = 4)]
        //public string Title { get; set; }


        [Display(Name = "检索内容", Description = "", Order = 5)]
        public string Content { get; set; }


        [Display(Name = "操作点", Description = "", Order = 6)]
        public int OperatingPoint { get; set; }


        [Display(Name = "创建人", Description = "", Order = 7)]
        [StringLength(20)]
        public string ADDWHO { get; set; }


        [Display(Name = "创建时间", Description = "", Order = 8)]
        public DateTime? ADDTS { get; set; }


        [Display(Name = "修改人", Description = "", Order = 9)]
        [StringLength(20)]
        public string EDITWHO { get; set; }


        [Display(Name = "修改日期", Description = "", Order = 10)]
        public DateTime? EDITTS { get; set; }


        [Display(Name = "操作类型", Description = "", Order = 10)]
        public LuneceIndexType IndexType { get; set; }
    }


}

注:盘古分词,词库配置文件PanGu.xml 必须放在Bin文件夹中否则会取默认目录:DLL所在路径/Dict/Dict.dct

重点类的说明

Analyzer类:LuceneNet中分词算法的基类 任何自定义算法都需继承它

FSDirectory类: 指定索引库文件存放文件位置  是Directory的子类(它有两个子类 还有一个RAMDirecory,它用来指定将索引库文件存放在内存中)

IndexReader:对索引进行读取的类

     静态方法bool  IndexExists(Directory directory)--判断目录directory是否是一个索引目录

IndexWriter:对索引进行写的类

     静态方法bool  IsLocked(Directory directory)--判断目录是否锁定

     它在对索引目录写之前会把目录锁定,两个IndexWrite无法同时操作一个索引文件

     IndexWrite在进行写操作的时候会自动加锁

     Close自动解锁

     Unlock手动解锁(通常用在程序异常退出 IndexWrite还没来得及close)

Document类:要检索的文档 相当于一条记录

     Add(Field field)向文档中添加字段

Filed类:构造函数(字段名,字段值,是否存储原文,是否对该字段创建索引,存储索引词间距)

     是否存储原文:Field.Store.YES 存储原值(如显示原内容必须为YES) Field.Store.NO不存储原值 Field.Store.YES压缩存储

     是否创建索引:Field.Index.NOT_ANALYZED不创建索引 Field.Index.ANALYZED创建索引(利于检索)

IndexSearcher:搜索类 Searcher类的子类

     Search(查询条件Query,过滤条件Filter,检索见过存放容器Collector)

Query类:所有查询条件父类(子类都具有Add方法)

     子类PhraseQuery:多个关键词的拼接类 关键词间是且的关系

     query.Add(new Term("字段名", 关键词))

     query.Add(new Term("字段名2", 关键词2)) 
     类似于:where 字段名 contains 关键词 and 字段名2 contains 关键词2




参考修改自:http://www.cnblogs.com/piziyimao/archive/2013/01/31/2887072.html

0 0
原创粉丝点击