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. ...
随机推荐
- dns简介
dns(domain name system),它是提供域名到ip的解析功能的系统.它和普通的系统一样,也是运行在服务器之上的. 1.dns指定的ip是用来干嘛的? 这个ip指向dns系统所在的机器. ...
- GCD使用dispatch_semaphore_t创建多线程网络同步请求
一.简介: dispatch_semaphore_t:表示信号,生成信号的方法是 dispatch_semaphore_t semaphore= dispatch_semaphore_create(0 ...
- Django基础——Model篇(一)
到目前为止,当程序涉及到数据库相关操作时,我们一般都会这么操作: (1)创建数据库,设计表结构和字段 (2)使用MySQLdb来连接数据库,并编写数据访问层代码 (3)业务逻辑层去调 ...
- web前端基础——jQuery编程进阶
1 jQuery本质 jQuery不是一门独立的语言,它是JavaScript的一个类库或框架.jQuery的核心思想就是:选取元素,对其操作.很多时候写jQuery代码的关键就是怎样设计合适的选择器 ...
- Android WebView Memory Leak WebView内存泄漏
在这次开发过程中,需要用到webview展示一些界面,但是加载的页面如果有很多图片就会发现内存占用暴涨,并且在退出该界面后,即使在包含该webview的Activity的destroy()方法中,使用 ...
- c++builder调用VC的dll以及VC调用c++builder的dll
解析__cdecl,__fastcall, __stdcall 的不同:在函数调用过程中,会使用堆栈,这三个表示不同的堆栈调用方式和释放方式. 比如说__cdecl,它是标准的c方法的堆栈调用方式,就 ...
- 网页二维码推广App的实现
移动互联网时代,一个APP的平均推广成本早已经超过了10块.而推广通常分二类: 1.已经下载过的用户,可以直接打开应用(一般人的手机上安装的应用都非常多,要快速找到某个应用是很困难的事情,而且Andr ...
- (转)投影矩阵的推导(Deriving Projection Matrices)
转自:http://blog.csdn.net/gggg_ggg/article/details/45969499 本文乃<投影矩阵的推导>译文,原文地址为: http://www.cod ...
- Nginx + FastCgi + Spawn-fcgi + c 的架构
参考: nginx+c/c++ fastcgi:http://www.yis.me/web/2011/11/01/66.htm cgi探索之路:http://github.tiankonguse.co ...
- C#代码像QQ的右下角消息框一样,无论现在用户的焦点在哪个窗口,消息框弹出后都不影响焦点的变化,那么有两种方法
你QQ的右下角消息框一样,无论现在用户的焦点在哪个窗口,消息框弹出后都不影响焦点的变化,那么有两种方法: 要么重写需要弹出的窗体的事件: protected override CreateParams ...