当前位置: 首页 > news >正文

.netcore的Lucene.Net基础应用

最近研究了一下使用.netcore的Lucene.Net应用,整理一下研究内容。

一、研究原因

1、系统环境:多终端、多服务、达梦数据库8、.netcore7.0、多机负载。

2、业务数量:单表1000万条数据,有7张的业务表或功能表有千万数据。

3、问题描述:业务表的字段较多,后台管理系统上,对数据查询的准确度与速度有要求,查询的组合字段较多,数据表上创建的索引无法完全覆盖所有的组合情况。


 

二、预期目标

1、有效提高查询速度。

2、持久化数据库与索引库保持一致。

3、减少对当前系统结构的影响,尽量降低改造的工作量。

4、可以进行索引库的数据量、待入索引库的数据、索引库查询速度等监控。


 

三、应用结构

1、因索引库只能单线程写入,可以多线程查询,所以在系统外新增索引写入服务,使多业务并发的状态形成单线程处理,根据业务表的类型,可以创建多个线程存入不同的索引库,同一索引库只有一个服务写入。

2、数据库增加触发器,当业务表增、删、改的时候,自动将业务表ID的操作存入队列表,使用触发器的方式避免多终端多服务的数据处置,保证业务表和索引库的数据一致。


 

四、实验结果

1、使用存储不分词索引导入1000万数据索引,检测多组合查询速度为1秒内。

2、业务表数据和索引库的数据可以保持一致。


 

五、代码样例

1、添加NuGet

1、达梦数据库 FreeSql.Provider.Dameng 3.5.213
2、索引 Lucene.Net 3.0.3
3、配置 System.Configuration.ConfigurationManager 9.0.9

2、写入索引库

using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Store;
using Lucene.Net.Util;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Reflection.Metadata;
using System.Data;
using Dm;
using static FreeSql.Internal.GlobalFilter;
using Lucene.Net.Search;
using Lucene.Net.QueryParsers;
using System.Runtime.ConstrainedExecution;
using System.Reflection.PortableExecutable;class Program
{static void Main(string[] args){Analyzer analyzer = null;IndexWriter writer = null;Lucene.Net.Store.Directory indexDirectory = null;try{indexDirectory = FSDirectory.Open(new System.IO.DirectoryInfo("D:\\LuceneIndex"));analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30);bool iscreate = !Lucene.Net.Index.IndexReader.IndexExists(indexDirectory);writer = new IndexWriter(indexDirectory, analyzer, iscreate, IndexWriter.MaxFieldLength.UNLIMITED);string connectionString = "Server=LOCALHOST;Database=SYSDBA;User Id=SYSDBA;Password=123456;";using (DmConnection connection = new DmConnection(connectionString)){connection.Open();using (DmCommand command = new DmCommand("SELECT reg_id,reg_name,reg_sex,reg_datetime,reg_status FROM reg_infor", connection)){using (DmDataAdapter adapter = new DmDataAdapter(command)){DataTable table = new DataTable();adapter.Fill(table);int i = 0;foreach (DataRow row in table.Rows){i++;Lucene.Net.Documents.Document doc = new Lucene.Net.Documents.Document();doc.Add(new Field("reg_id", row["reg_id"].ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));//存储,不分词索引doc.Add(new Field("reg_name", row["reg_name"].ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));//存储,不分词索引doc.Add(new Field("reg_sex", row["reg_sex"].ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));//存储,分词索引doc.Add(new Field("reg_datetime", row["reg_datetime"].ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));//存储,分词索引doc.Add(new Field("reg_status", row["reg_status"].ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));writer.AddDocument(doc);writer.Commit();//.Optimize();
                        }}}connection.Close();}}catch (Exception ex){throw;}finally{if (analyzer != null)analyzer.Close();if (writer != null)writer.Dispose();//之前为:writer.Close();if (indexDirectory != null)indexDirectory.Dispose();//之前使用Close();
        }Console.WriteLine("索引创建成功!");Console.ReadLine();}
}

3、数据查询

using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Store;
using Lucene.Net.Util;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Reflection.Metadata;
using System.Data;
using Dm;
using static FreeSql.Internal.GlobalFilter;
using Lucene.Net.Search;
using Lucene.Net.QueryParsers;
using System.Runtime.ConstrainedExecution;
using System.Reflection.PortableExecutable;class Program
{static void Main(string[] args){Analyzer analyzer = null;IndexWriter writer = null;Lucene.Net.Store.Directory indexDirectory = null;try{indexDirectory = FSDirectory.Open(new System.IO.DirectoryInfo("D:\\LuceneIndex"));analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30);var directory = FSDirectory.Open("D:\\LuceneIndex");var reader = DirectoryReader.Open(directory, true);var searcher = new IndexSearcher(reader);int numDocs = reader.NumDocs();
var booleanQuery = new BooleanQuery();booleanQuery.Add(new TermQuery(new Term("reg_status", "1")), Occur.MUST);booleanQuery.Add(new TermQuery(new Term("reg_sex", "1")), Occur.MUST);var hits = searcher.Search(booleanQuery, 10);foreach (var hit in hits.ScoreDocs){var doc = searcher.Doc(hit.Doc);Console.WriteLine($"ID: {doc.Get("reg_id")}, Name: {doc.Get("reg_name")}");}}catch (Exception ex){throw;}finally{if (analyzer != null)analyzer.Close();if (writer != null)writer.Dispose();//之前为:writer.Close();if (indexDirectory != null)indexDirectory.Dispose();//之前使用Close();
        }Console.WriteLine("索引查询成功!");Console.ReadLine();}
}

4、触发器

---新增数据触发器---
CREATE TRIGGER trg_after_insert_reginfor AFTER INSERT ON reg_infor FOR EACH ROW BEGINinsert into SYSDBA.ACTION_LOG(
"LOG_ID", "BIN_ID", "ACTION_TYPE", "ACTION_STATUS", "CREATE_TIME", "ACTION_TIME") VALUES (REPLACE(SYS_GUID(), '-', ''),NEW."reg_id", 1, 0,TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'),''); END;
---修改数据触发器---
CREATE TRIGGER trg_after_update_reginfor AFTER UPDATE ON reg_infor FOR EACH ROW BEGINinsert into SYSDBA.ACTION_LOG(
"LOG_ID", "BIN_ID", "ACTION_TYPE", "ACTION_STATUS", "CREATE_TIME", "ACTION_TIME") VALUES (REPLACE(SYS_GUID(), '-', ''),NEW."reg_id", 2, 0,TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'),''); END;

 

http://www.gsyq.cn/news/8584.html

相关文章:

  • 在Ubuntu 16.04上安装openjdk-6/7/8-jdk的步骤
  • 物流行业信息咨询智能问答系统
  • 线性代数 行列式 | 子式 / 主子式 / 顺序主子式 / 余子式 / 代数余子式 - 教程
  • HBase 的自带命令行工具 hbase shell 的基本使用
  • 重塑公司绩效管理的 6 种方法
  • Confluent-Kafka-go 发布超过 1M 消息失败困难克服
  • 组件重新装载时 useSWR 会发起请求
  • Seedream 4.0 简直绝了!
  • mysql查询死锁,mysql查询死锁方法
  • 【IEEE出版、已连续5届稳定快速EI检索】第六届计算机工程与智能控制学术会议(ICCEIC 2025)
  • 向上一步——当做事纠结的人停止决策内耗,你就是掌控自己的神!
  • Windows平台安装cocos2d-x V3.17.2
  • 深入解析:vue 批量自动引入并注册组件或路由
  • 【IEEE出版、已连续6届EI稳定检索】第七届机器学习、大数据与商务智能国际会议 (MLBDBI 2025)
  • 构建AI智能体:三十八、告别“冷启动”:看大模型如何解决推荐系统的世纪难题 - 实践
  • EMS 抗扰度在边缘计算产品电路设计的基本问题 - 教程
  • C#依赖注入
  • 完整教程:Docker Compose 一键启动多容器服务
  • [MCP][07]logging和progress等功能说明
  • 端口命令
  • c-store发送dcm文件超时
  • 【2025-09-19】连岳摘抄
  • MAUI和Android、IOS的互操作之IOS篇
  • 【Java】Hashtable讲解
  • 【JAVA】TreeSet讲解
  • 批判 vs 审判
  • ctfshow web入门 SSRF
  • C#中避免GC压力和提高性能的8种技术
  • UNIX网络编程笔记:共享内存区和远程过程调用 - 指南
  • 函数内联