`

二十七、Luence在项目中运用

 
阅读更多

public class LuceneContext {


    private static LuceneContext instance;
    private static final String INDEX_PATH = "d:/lucene/test";
    private static IndexWriter writer;
    private static Analyzer analyzer;
    private static Version version;
    private static NRTManager nrtMgr;
    private static SearcherManager mgr;
    private static Directory directory;
    private LuceneContext(){}
   
    public static LuceneContext getInstance() {
        if(instance==null){
            System.out.println("init");
            init();
            instance = new LuceneContext();
        }
        return instance;
    }
   
    private static void init() {
        try {
            directory = FSDirectory.open(new File(INDEX_PATH));
            version = Version.LUCENE_35;
            String dicUrl = LuceneContext.class.getClassLoader().getResource("data").getPath();
            analyzer = new MMSegAnalyzer(dicUrl);
            writer = new IndexWriter(directory,new IndexWriterConfig(version,analyzer));
            nrtMgr = new NRTManager(writer, new SearcherWarmer() {
                @Override
                public void warm(IndexSearcher arg0) throws IOException {
                    System.out.println("reopen index");
                }
            });
            mgr = nrtMgr.getSearcherManager(true);
           
            NRTManagerReopenThread reopenThread = new NRTManagerReopenThread(nrtMgr, 5.0,0.025);
            reopenThread.setName("NRTManager reopen thread");
            reopenThread.setDaemon(true);
            reopenThread.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
   
    public IndexSearcher getSearcher() {
        return mgr.acquire();
    }
   
    public void releaseSearcher(IndexSearcher searcher) {
        try {
            mgr.release(searcher);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
   
    public void commitIndex() {
        try {
            writer.commit();
            writer.forceMerge(3);
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
   
    public NRTManager getNRTManager() {
        return nrtMgr;
    }
   
    public Version getVersion() {
        return version;
    }
   
    public Analyzer getAnalyzer() {
        return analyzer;
    }
}



public class IndexField {


    private String id;
    private String title;
    private List<String> content;
    private List<String> atths;
    private int parentId;
    private int objId;
    private Date createDate;
    private String type;


public class Index {
   
    private int msgId;
    private String title;
    private String summary;
    private Date createDate;


@Entity
@Table(name="temp_index")
public class TempIndex {
   
    private int id;
    private int objId;
    private String type;//Message,Attachment
    private int operator;



@Service("indexService")
public class IndexService implements IIndexService {



    private Document field2Doc(IndexField field) {
        Document doc = new Document();
        doc.add(new Field("id",field.getId(),Field.Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS));
        doc.add(new Field("title",field.getTitle(),Field.Store.YES,Field.Index.ANALYZED));
        for(String content:field.getContent()) {
            doc.add(new Field("content",content,Field.Store.NO,Field.Index.ANALYZED));
        }
        if(field.getAtths()!=null) {
            for(String att:field.getAtths()) {
                doc.add(new Field("atts",att,Field.Store.YES,Field.Index.NO));
            }
        }
        doc.add(new NumericField("objId",Field.Store.YES,true).setIntValue(field.getObjId()));
        doc.add(new NumericField("createDate",Field.Store.YES,true).setLongValue(field.getCreateDate().getTime()));
        return doc;
    }


    @Override
    public void addIndex(IndexField fields,boolean inDatabase) {
        try {
            if(inDatabase) {
                TempIndex ti = new TempIndex();
                ti.setAdd();
                ti.setObjId(fields.getObjId());
                ti.setType(fields.getType());
                tempIndexDao.add(ti);
            }
            NRTManager nrtMgr = LuceneContext.getInstance().getNRTManager();
            Document doc = field2Doc(fields);
            nrtMgr.addDocument(doc);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void deleteIndex(String id,String type) {
        try {
            TempIndex ti = new TempIndex();
            ti.setDelete();
            ///xx_xx
            ti.setId(Integer.parseInt(id));
            ti.setType(type);
            tempIndexDao.add(ti);
            LuceneContext.getInstance().getNRTManager().deleteDocuments(new Term("id",id));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void updateIndex(IndexField fields) {
        try {
            TempIndex ti = new TempIndex();
            ti.setDelete();
            ///xx_xx
            ti.setId(fields.getObjId());
            ti.setType(fields.getType());
            tempIndexDao.add(ti);
            NRTManager nrtMgr = LuceneContext.getInstance().getNRTManager();
            Document doc = field2Doc(fields);
            nrtMgr.updateDocument(new Term("id",fields.getId()), doc);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    private String highligher(String text,Query query,String field) {
        try {
            QueryScorer scorer = new QueryScorer(query);
            Fragmenter fragmenter = new SimpleSpanFragmenter(scorer);
            Formatter formatter = new SimpleHTMLFormatter("<span class='lighter'>","</span>");
            Highlighter lighter = new Highlighter(formatter,scorer);
            lighter.setTextFragmenter(fragmenter);
            String ht = lighter.getBestFragment(LuceneContext.getInstance().getAnalyzer(),
                    field,text);
            if(ht==null) {
                if(text.length()>=200) {
                    text = text.substring(0, 200);
                    text=text+"....";
                }
                return text;
            }
            else return ht.trim();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InvalidTokenOffsetsException e) {
            e.printStackTrace();
        }
        return text;
    }


    private ScoreDoc getLastDoc(int pageOffset,IndexSearcher searcher,Query query) {
        if(pageOffset<=0) return null;
        try {
            TopDocs tds = searcher.search(query,pageOffset-1);
            return tds.scoreDocs[pageOffset-1];
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    @Override
    public PageObject<Index> findByIndex(String condition) {
        if(condition==null) condition = "";
        IndexSearcher searcher = LuceneContext.getInstance().getSearcher();
        PageObject<Index> pages = new PageObject<Index>();
        List<Index> datas = new ArrayList<Index>();
        try {
            int pageSize = SystemContext.getPageSize();
            int pageOffset = SystemContext.getPageOffset();
            MultiFieldQueryParser parser = new MultiFieldQueryParser(LuceneContext.getInstance().getVersion(),
                        new String[]{"title","content"}, LuceneContext.getInstance().getAnalyzer());
            Query query = parser.parse(condition);
            TopDocs tds = searcher.searchAfter(getLastDoc(pageOffset,searcher,query),
                          query, pageSize);
            int totalRecord = tds.totalHits;
            List<Integer> msgs = new ArrayList<Integer>();
            for(ScoreDoc sd:tds.scoreDocs) {
                Document doc = searcher.doc(sd.doc);
                Index index = new Index();
                index.setCreateDate(new Date(Long.parseLong(doc.get("createDate"))));
                String title = doc.get("title");
                index.setTitle(highligher(title,query,"title"));
                String[] ans = doc.getValues("atts");
                StringBuffer content = new StringBuffer();
                if(ans!=null) {
                    for(String fn:ans) {
                        content.append(IndexUtil.file2String(fn));
                    }
                }
                index.setSummary(content.toString());
                int msgId = Integer.parseInt(doc.get("id"));
                index.setMsgId(msgId);
                msgs.add(msgId);
                datas.add(index);
            }
            Map<Integer,String> contents = messageDao.listMessageContent(msgs);
            for(int i=0;i<datas.size();i++) {
                Index index = datas.get(i);
                String content = contents.get(index.getMsgId());
                content = content+index.getSummary();
                datas.get(i).setSummary(highligher(content,query,"content"));
            }
           
            pages.setDatas(datas);
            pages.setOffset(pageOffset);
            pages.setPageSize(pageSize);
            pages.setTotalRecord(totalRecord);
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TikaException e) {
            e.printStackTrace();
        } finally {
            LuceneContext.getInstance().releaseSearcher(searcher);
        }
        return pages;
    }


    private void indexMessage(Message msg) {
        List<String> contents = new ArrayList<String>();
        List<String> ans = new ArrayList<String>();
        contents.add(msg.getContent());
        List<Attachment> atts = attachmentDao.listByMessage(msg.getId());
        for(Attachment att:atts) {
            IndexUtil.attach2Index(contents, ans,att);
        }
        IndexField field = IndexUtil.msg2IndexField(msg);
        field.setContent(contents);
        field.setAtths(ans);
        addIndex(field,false);
    }


    private void indexMessages(List<Message> messages) {
        for(Message msg:messages) {
            indexMessage(msg);
        }
    }


    @Override
    public void updateReconstructorIndex() {
        /**
         * 将数据库中的所有对象取出,创建相应的IndexField完成索引的重构
         */
        try {
            LuceneContext.getInstance().getNRTManager().deleteAll();
            List<Message> messages = messageDao.list("from Message");
            indexMessages(messages);
            LuceneContext.getInstance().commitIndex();
            tempIndexDao.delAll();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void updateSetIndex() {
        List<TempIndex> tis = tempIndexDao.list("from TempIndex");
        for(TempIndex ti:tis) {
            if(ti.getType().equals(IndexUtil.MSG_TYPE)) {
                Message msg = messageDao.load(ti.getObjId());
                indexMessage(msg);
            }
        }
        LuceneContext.getInstance().commitIndex();
        tempIndexDao.delAll();
    }


    @Override
    public void updateCommitIndex() {
        tempIndexDao.delAll();
        LuceneContext.getInstance().commitIndex();
    }

}


public class CleanListener implements ServletContextListener {

    private Timer indexTimer;

    private WebApplicationContext wac = null;


    private class IndexCommit extends TimerTask {
        @Override
        public void run() {
            SystemContext.setRealPath(realPath);
            System.out.println("索引进行了提交"+new Date());
            IIndexService indexService = (IIndexService)wac.getBean("indexService");
            indexService.updateCommitIndex();
        }
    }


    @Override
    public void contextInitialized(ServletContextEvent sce) {
        //可以获取spring中BeanFactory,这个BeanFactory是在系统启动的时候就完成存储了
        wac = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
        System.out.println("------------------清理的启动程序已经开启(已经获取了"+wac+")---------------------");
        realPath = sce.getServletContext().getRealPath("");
        timer = new Timer();
        timer.scheduleAtFixedRate(new ClearDataTask(),50000, 300000);
        indexTimer = new Timer();
        indexTimer.scheduleAtFixedRate(new IndexCommit(), 600000, 600000);
    }


分享到:
评论

相关推荐

    Luence in Action 中英文pdf 版

    8. **实战案例**:书中包含多个实际项目案例,帮助读者将理论知识转化为实践,包括构建搜索引擎、日志分析和内容管理系统等。 9. **Lucene最新版本特性**:英文版可能会包含Lucene的最新版本特性,比如新的API、...

    luence搜索

    在实际项目中,通常会结合数据库来使用Lucene。首先,从数据库读取数据,然后构建Lucene文档并建立索引。当数据库中的数据发生变化时,需要同步更新Lucene索引,确保搜索结果的准确性。此外,还可以通过优化索引策略...

    Luence+Ikanalyzer+stopword+dic

    在Lucene中,为了提高搜索的准确性和效率,通常会使用到一些优化技术,如分词器(Analyzer)和停用词表(Stopword List)。Ikanalyzer是专门为中文处理设计的一个分词器,而stopword+dic则涉及到如何定制和使用...

    方启明_王宇翔1

    他的研究领域涵盖人工智能的核心技术,这些技术在现代智能系统中扮演着关键角色。 王宇翔博士,毕业于东南大学计算机科学与工程学院,专长在于大数据近似查询优化、RDF知识库语义查询和分布式数据处理。他在这些...

    COMSOL激光增材制造技术:热流力三场耦合模型的构建与模拟研究,COMSOL激光增材制造中热-流-力三场耦合模型的研究与应用:基于固体传热、固体力学、层流和动网格技术的多物理场分析,comsol激光

    COMSOL激光增材制造技术:热流力三场耦合模型的构建与模拟研究,COMSOL激光增材制造中热-流-力三场耦合模型的研究与应用:基于固体传热、固体力学、层流和动网格技术的多物理场分析,comsol激光增材制造热-流-力三场偶合模型 选用固体传热,固体力学,层流和动网格,考虑热物性以及马兰戈尼效应、表面张力,相变潜热,热对流和热辐射等 【软件工具】COMSOL5.6 【备注】,comsol三维模型 ,核心关键词:comsol; 激光增材制造; 热-流-力三场偶合模型; 固体传热; 固体力学; 层流; 动网格; 热物性; 马兰戈尼效应; 表面张力; 相变潜热; 热对流; 热辐射; COMSOL5.6; 三维模型。,COMSOL 5.6激光增材制造三场耦合模型

    基于PLL的SMO滑模观测器算法在永磁同步电机无传感器矢量控制中的应用及其与反正切SMO的对比:有效消除转速抖动,基于PLL的SMO滑模观测器算法在永磁同步电机无传感器矢量控制中的应用及其与反正切SM

    基于PLL的SMO滑模观测器算法在永磁同步电机无传感器矢量控制中的应用及其与反正切SMO的对比:有效消除转速抖动,基于PLL的SMO滑模观测器算法在永磁同步电机无传感器矢量控制中的应用及其与反正切SMO的对比:有效消除转速抖动,基于PLL的SMO滑模观测器算法,永磁同步电机无传感器矢量控制,跟基于反正切的SMO做对比,可以有效消除转速的抖动。 ,基于PLL的SMO滑模观测器算法; 永磁同步电机无传感器矢量控制; 反正切SMO; 转速抖动消除。,基于PLL SMO滑模观测器:永磁同步电机无传感器矢量控制新算法,优化抖动消除效能

    【毕业设计】java-springboot+vue个人云盘管理系统实现源码(完整前后端+mysql+说明文档+LunW).zip

    【毕业设计】java-springboot+vue个人云盘管理系统实现源码(完整前后端+mysql+说明文档+LunW).zip

    【语音识别】基于matlab自适应滤波器LMS算法鸟类物种识别【含Matlab源码 9977期】.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    【毕业设计】java-springboot-vue电影推荐系统实现源码(完整前后端-mysql-说明文档-LunW).zip

    【毕业设计】java-springboot-vue电影推荐系统实现源码(完整前后端-mysql-说明文档-LunW).zip

    基于OpenCV和Python的实时口罩识别系统:支持摄像头与图片检测,界面简洁操作便捷,基于OpenCV的口罩识别系统 相关技.

    基于OpenCV和Python的实时口罩识别系统:支持摄像头与图片检测,界面简洁操作便捷,基于OpenCV的口罩识别系统 相关技术:python,opencv,pyqt (请自行安装向日葵远程软件,以便提供远程帮助) 软件说明:读取用户设备的摄像头,可实时检测画面中的人的口罩佩戴情况,并给予提示。 有基础的同学,可稍作修改,检测图片。 第一张为运行主界面。 第二张为部分代码截图。 第三和第四张为运行界面。 ,基于OpenCV的口罩识别系统; Python; OpenCV; PyQt; 远程协助; 摄像头读取; 实时检测; 口罩佩戴情况提示; 代码截图; 运行界面。,"基于OpenCV与Python的口罩识别系统:实时检测与提醒"

    Git与GitHub入门指南:版本控制、协作开发及基础命令教程

    内容概要:本文是一份关于 Git 和 GitHub 的入门指南,详细介绍了一整套从安装到进阶使用的完整流程。文章首先阐述了版本控制的重要性,并解释了 Git 的特点和优势。接着逐步介绍了 Git 和 GitHub 的使用方法,包括安装设置 Git、创建和管理 GitHub 账户、创建和克隆仓库,以及日常操作如提交、推送、拉取、分支管理和处理冲突的具体指令和操作步骤。还涉及到高级主题如合并请求、持续集成等功能的介绍,帮助读者深入了解 Git 和 GitHub 的应用范围和最佳实践。 适用人群:适用于刚开始接触版本控制系统的初学者,特别是那些正在寻找 Git 和 GitHub 实际操作指导的学生和技术爱好者。 使用场景及目标:①为刚踏入软件开发领域的新人提供详尽的基础教学,使其能够快速理解和掌握必要的技能;②指导已有一定经验但仍想进一步深化理解的开发人员如何优化日常工作流程;③促进团队合作效率提升,通过具体的实例演示如何利用版本控制系统协调多人协作。 其他说明:随着 Git 和 GitHub 成为现代软件开发的标准工具之一,这份资料不仅涵盖了关键知识点,而且配有多图例解析和实操练习,确保每个阶段的学习都能得到良好反馈和支持。读者可以通过动手实践来巩固所学知识,在实践中遇到困难也能及时参考本文获得解决方案。

    python安装-16. 使用指定序列和数值创建一个字典-分配伴侣.py

    python安装-16. 使用指定序列和数值创建一个字典——分配伴侣.py

    Python+OpenCV魔方识别系

    本研究的目的是基于Python和OpenCV开发一个魔方识别系统,并提供相应的源码和部署教程。通过该系统,用户可以将魔方的图像输入,系统可以自动识别魔方的状态,并给出相应的还原方案。具体来说,本研究的主要内容包括以下几个方面: 图像预处理:通过使用OpenCV提供的图像处理算法,对输入的魔方图像进行预处理,包括图像去噪、边缘检测、图像分割等操作,以提高后续的识别准确率。 特征提取与模式识别:通过使用OpenCV提供的特征提取算法,对预处理后的图像进行特征提取,以获取魔方的状态信息。然后,通过机器学习算法,对提取到的特征进行模式识别,以确定魔方的状态。 还原方案生成:根据识别到的魔方状态,使用经典的还原算法,生成相应的还原方案。通过该方案,用户可以轻松地还原魔方,提高解决效率。

    基于Springboot与Vue.js的WMS仓库管理系统源码详解:前后端分离架构下的Java实践与功能详述,基于Springboot和Vue的前后端分离WMS仓库管理系统源码,详细功能参考详情 ,S

    基于Springboot与Vue.js的WMS仓库管理系统源码详解:前后端分离架构下的Java实践与功能详述,基于Springboot和Vue的前后端分离WMS仓库管理系统源码,详细功能参考详情。,Springboot vue仓库管理系统源码Java 前后端分离 WMS仓库管理 BS 功能见详情 ,Springboot; Vue; 仓库管理系统; 源码; Java; 前后端分离; WMS仓库管理; BS; 功能详情,Springboot+Vue仓库管理系统源码:前后端分离的WMS管理BS应用

    用AI学安卓游戏开发1-控制小球上下左右移动2代码

    用AI学安卓游戏开发1——控制小球上下左右移动2代码, 初始化小球随机自有移动,遇到屏幕边缘反弹,摇杆介入后小球停止自有移动,按照摇杆控制方向移动。

    【图像融合】基于matlab拉普拉斯方法水下图像增强融合【含Matlab源码 9983期】复现.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    【图像加密】基于matlab差分扩展缩略图保持加密【含Matlab源码 9692期】.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    【图像重建】CT图像重建【含Matlab源码 8035期】.md

    CSDN Matlab武动乾坤上传的资料均是完整代码运行出的仿真结果图,可见完整代码亲测可用,适合小白; 1、完整的代码内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描博客文章底部QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    基于ATP-EMTP的110kV海底电缆与架空线雷击过电压仿真分析与研究,基于ATP-EMTP的110kV海底电缆与架空线雷击过电压仿真分析与研究,110kV海底电缆-架空线雷击过电压ATP-EMTP

    基于ATP-EMTP的110kV海底电缆与架空线雷击过电压仿真分析与研究,基于ATP-EMTP的110kV海底电缆与架空线雷击过电压仿真分析与研究,110kV海底电缆-架空线雷击过电压ATP-EMTP仿真分析 ,核心关键词: 110kV海底电缆; 架空线; 雷击过电压; ATP-EMTP仿真分析; 分析。 关键词用分号分隔,如上所示。,雷击过电压仿真分析:110kV海底电缆及架空线ATP-EMTP研究

    基于800kV高压直流输电的VSC-HVDC仿真模型研究:控制策略与性能分析,基于800kV-VSC-HVDC的直流输电仿真模型研究:深入探讨控制结构与电压稳定性,800kV-VSC-HVDC直流输电

    基于800kV高压直流输电的VSC-HVDC仿真模型研究:控制策略与性能分析,基于800kV-VSC-HVDC的直流输电仿真模型研究:深入探讨控制结构与电压稳定性,800kV-VSC-HVDC直流输电仿真模型(Matlab) 流器拓扑:VSC两电平流器 电压等级:直流800kV,交流500kV 控制结构:逆变侧定有功控制与电流内环PI+前馈解耦,整流侧定直流电压与电流内环+PI前馈解耦; 输电距离:100km; 双端电压电流均为对称的三相电压电流; 直流电压稳定在800kV; 双端网侧THD<2% 电子资料, ,800kV; VSC HVDC; 直流输电仿真模型; Matlab; VSC两电平换流器; 直流电压稳定; 逆变侧定有功控制; 电流内环PI+前馈解耦; 整流侧定直流电压与电流内环; 输电距离; 双端电压电流对称; 双端网侧THD<2%。,Matlab仿真模型:800kV VSC两电平换流器HVDC输电系统

Global site tag (gtag.js) - Google Analytics