lucene.net的一个动态更新类
工作的需要,需要对于lucene.net索引即时的更新,毕竟lucene.net的索引重建的话比较慢,数据量大的时候建下要几天,所以就写个了缓冲类来解决即时的更新的问题,其实还是比较简单的。
大体上的原理就是创建的时候创建两组Directory 一组在内存中,一组在硬盘上,搜索的时候可以进行合并去搜索,后续的操作都直接暂放到内存中,定时的去同步到硬盘上,删除或者更新的时候内存中有一缓存Query,用来排除被更新或者删除的内容,当搜索的时候,自动忽略掉这部分的内容去集中,就解决了大多数的问题了。
OK.看代码的实现。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using S = System.Timers; using IO = System.IO; using Lucene.Net.Documents; using Lucene.Net.Store; using Lucene.Net.Search; using Lucene.Net.Index; using Lucene.Net.Analysis; using System.Collections; using Lucene.Net.Analysis.MMSeg; namespace SearchSample { public class BufferDirectory { private static readonly Analyzer _analysis; private static readonly string _path; private static RAMDirectory _ramIndex; private static readonly IndexWriter _ramWrite; private static BufferDirectory _directory; private static object _lock = new object(); private static BooleanQuery _query = new BooleanQuery(); private static object _querylock = new object(); static BufferDirectory() { _path = IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Index"); _ramIndex = new RAMDirectory(); _ramWrite = new IndexWriter(_ramIndex, DefaultAnalyzer.Analyzer, true, IndexWriter.MaxFieldLength.LIMITED); _analysis = DefaultAnalyzer.Analyzer; var tmpFs = FSDirectory.Open(_path); if (Lucene.Net.Index.IndexReader.IndexExists(tmpFs)) { using (IndexWriter tmp = new IndexWriter(tmpFs, _analysis, false, IndexWriter.MaxFieldLength.LIMITED)) { } } else { using (IndexWriter tmp = new IndexWriter(tmpFs, _analysis, true, IndexWriter.MaxFieldLength.LIMITED)) { } } } ~BufferDirectory() { _ramIndex.Dispose(); _ramWrite.Dispose(); _query = null; } public static BufferDirectory InitConfig() { if (_directory == null) { lock (_lock) { if (_directory == null) { _directory = new BufferDirectory(); } } } return _directory; } public static BufferDirectory Instance() { return _directory; } /// <summary> /// 重启缓存区 /// </summary> public static void Reset() { lock (_lock) { _directory = null; InitConfig(); } lock (_querylock) { _query = null; _query = new BooleanQuery(); } return; } /// <summary> /// 初始化的时候注册,注册为全局生效 /// </summary> /// <param name="before"></param> public static void BeforeConfig(BeforeSetDocument before) { if (_directory == null) { throw new NullReferenceException("BufferDirectory为空"); } _directory.BeforeSetDocumentHandler += before; return; } /// <summary> /// 初始化的时候注册,注册为全局生效 /// </summary> /// <param name="after"></param> public static void AfterConfig(AfterSetDocument after) { if (_directory == null) { throw new NullReferenceException("BufferDirectory为空"); } _directory.AfterSetDocumentHandler += after; return; } /// <summary> /// 更新删除Query /// </summary> /// <param name="query"></param> /// <returns></returns> public static void IgnoreQuery(Query query, Occur occur) { lock (_querylock) { _query.Add(query, occur); } return; } public static Query IgnoreQuery() { return _query; } public delegate void BeforeSetDocument(Document document); public event BeforeSetDocument BeforeSetDocumentHandler; public delegate void AfterSetDocument(Document document); public event AfterSetDocument AfterSetDocumentHandler; private BufferDirectory() { } //public void SetIndexWriter(Action<IndexWriter> action) //{ // action(_index2); // return; //} public void CreateDocument(Document documnet) { try { if (BeforeSetDocumentHandler != null) BeforeSetDocumentHandler(documnet); _ramWrite.AddDocument(documnet); if (AfterSetDocumentHandler != null) AfterSetDocumentHandler(documnet); } catch { } finally { _ramWrite.Commit(); } return; } public static void UpdateOrSaved() { _ramWrite.Optimize(); using (IndexWriter update = new IndexWriter(FSDirectory.Open(_path), _analysis, false, IndexWriter.MaxFieldLength.LIMITED)) { try { update.AddIndexes(IndexReader.Open(_ramIndex, true)); update.DeleteDocuments(_query); update.Commit(); update.Optimize(); } catch { } finally { _ramIndex.Dispose(); _ramIndex = null; _ramIndex = new RAMDirectory(); using (IndexWriter tmp = new IndexWriter(_ramIndex, _analysis, true, IndexWriter.MaxFieldLength.LIMITED)) { } } } return; } public static IndexReader Reader() { return new MultiReader(IndexReader.Open(FSDirectory.Open(_path), false), IndexReader.Open(_ramIndex, false)); } } }
大体上也就这样逻辑,但是还有一个就是内存中的索引持久问题,毕竟如果不进行持久,在AppDomain重启会导致内存中的索引删除,而导致的索引不同步。
这样可以通过BeforeSetDocumentHandler 和AfterSetDocumentHandler事件来写入到持久的临时缓冲器,加载的时候自动优先加载这部分的临时缓存区,于是就算比较完整的实现lucene.net动态维护了。
当然这些是比较粗暴的方法,还有一些更好的维护策略,就以后再慢慢总结了。
lucene.net的一个动态更新类的更多相关文章
- vue+vuex+axios+echarts画一个动态更新的中国地图
一. 生成项目及安装插件 # 安装vue-cli npm install vue-cli -g # 初始化项目 vue init webpack china-map # 切到目录下 cd china- ...
- JAVA代码热部署,在线不停服动态更新
本地debug的时候,可以实时编译并更新代码,线上也可以不停服来动态更新类,即所说的java热部署. JDK代理的两种方式: 1.premain方式是Java SE5开始就提供的代理方式,但其必须 ...
- C++学习之动态数组类的封装
动态数组(Dynamic Array)是指动态分配的.可以根据需求动态增长占用内存的数组.为了实现一个动态数组类的封装,我们需要考虑几个问题:new/delete的使用.内存分配策略.类的四大函数(构 ...
- ajax动态更新下拉列表
前面做了一个ajax的小demo,今天看一个动态更新下拉列表,或者也叫级联更新下拉列表,这个也是利用ajax的异步调用去后台实现数据请求.然后回到前台完毕下拉列表数据的更新,以增强web应用的交互性. ...
- Unity热更新之C#反射动态获取类属性及方法
如果我们要为发布出去的游戏更新一些功能,但又不想让用户重新下载整个游戏包,只让他下载我们更新的资源包,用assetBundle打包资源的方式是可以的,但其中有个最大的例外,那就是脚本. 虽然asset ...
- Vue父组件向子组件传递一个动态的值,子组件如何保持实时更新实时更新?
原文:https://blog.csdn.net/zhouweixue_vivi/article/details/78550738 2017年11月16日 14:22:50 zhouweixue_vi ...
- C#编写了一个基于Lucene.Net的搜索引擎查询通用工具类:SearchEngineUtil
最近由于工作原因,一直忙于公司的各种项目(大部份都是基于spring cloud的微服务项目),故有一段时间没有与大家分享总结最近的技术研究成果的,其实最近我一直在不断的深入研究学习Spring.Sp ...
- java动态更新枚举类
工作中遇到需要对枚举类的值进行动态更新 手动改不现实也不方便 现记录下来方便以后学习使用 1.在工程utils包中添加动态更新枚举类得工具类(根据自己得项目,放到指定位置调用就可以) 2.一开始陷入了 ...
- 模仿.NET框架ArrayList写一个自己的动态数组类MyArrayList,揭示foreach实现原理
通过.NET反编译工具可以查看到ArrayList内部的代码,发现ArrayList并非由链表实现,而是由一个不断扩容的数组对象组成. 下面模仿ArrayList写一个自己的MyArrayList. ...
随机推荐
- GIt 从入门到放弃
一.注册github账号 github网址https://github.com/ 下一步 然后,你的邮箱会收到一封邮件,进行邮箱验证就行了 二.创建github仓库 登录你的github,在首页的右方 ...
- CI框架笔记
@update 2016-4-2 13:45:35 一.目录结构 ci_demo ├─myapp 应用主目录 │ ├─autoload.php 自定义的自动加载文件(可选) │ ├─myapp.php ...
- 【Android】进入Material Design时代
由于本文引用了大量官方文档.图片资源,以及开源社区的Lib和相关图片资源,因此在转载的时候,务必注明来源,如果使用资源请注明资源的出处,尊重版权,尊重别人的劳动成果,谢谢! Material Desi ...
- 使用Swift代码演示Cocoa框架
通过使用简单的代码学习Cocoa框架,每一个例子都通过代码和StoryBoard实现,并且总结他们的各自特点 所有完整代码将会托管到github库,https://github.com/land-pa ...
- paip..禁用mmseg 的默认词库. . 仅仅使用自定义词库from数据库.
paip..禁用mmseg 的默认词库. . 仅仅使用自定义词库from数据库. mmseg默认词库只能是文件格式...不好维护..要是不个词库放的个数据库里面走好维护兰.. 要实现2个目标..: 1 ...
- Windows对象操作:浏览器窗口信息
属性(值或者子对象):opener:打开当前窗口的源窗口,如果当前窗口是首次启动浏览器打开的,则opener是null,可以利用这个属性来关闭源窗口. 属性:Windows.shuxing; 方法(函 ...
- Java攻城狮面试考题
<html> <head> <meta http-equiv="Content-Type" content="text/html; char ...
- android: 服务的生命周期
9.4 服务的生命周期 之前章节我们学习过了活动以及碎片的生命周期.类似地,服务也有自己的生命周期, 前面我们使用到的 onCreate().onStartCommand().onBind()和 ...
- GCD的同步异步串行并行、NSOperation和NSOperationQueue一级用dispatch_once实现单例
转:http://www.tuicool.com/articles/NVVnMn (1)GCD实现的同步异步.串行并行. ——同步sync应用场景:用户登录,利用阻塞 ——串行异步应用场景:下载等耗时 ...
- StringBuffer&StringBuilder区别详解
序言 StringBuffer与StringBuilder是java.lang包下被大家熟知的两个类.其异同为:一.长度都是可扩充的:二.StringBuffer是线程安全的,StringBuilde ...