1:Lucene
Lucene是一个全文搜索框架,而不是应用产品。因此它并不像www.baidu.com 或者google Desktop那么拿来就能用,它只是提供了一种工具让你能实现这些产品。
2:Pangu分词
盘古分词是一个中英文分词组件。
借用以上两个组件可以对中文分词实现全文搜索。
先说下大概概念
//一、Document
//Document:文档对象,是一条原始的数据
//二、Field
//如果一个字段要显示到最终的结果中,那么一定要存储,否则就不存储
//如果要根据这个字段进行搜索,那么这个字段就必须创建索引。
//如何确定一个字段是否需要分词?
//前提是这个字段首先要创建索引。然后如果这个字段的值是不可分割的,那么就不需要分词。例如:ID
//DoubleField、FloatField、IntField、LongField、StringField、TextField这些子类一定会被创建索引,但是不会被分词,而且不一定会被存储到文档列表。要通过构造函数中的参数Store来指定:如果Store.YES代表存储,Store.NO代表不存储
//TextField即创建索引,又会被分词。StringField会创建索引,但是不会被分词。
//StoreField一定会被存储,但是一定不创建索引
//三、Directory
//FSDirectory:文件系统目录,会把索引库指向本地磁盘。
//特点:速度略慢,但是比较安全
//RAMDirectory:内存目录,会把索引库保存在内存。
//特点:速度快,但是不安全
//四、Analyzer(分词器类) 若有中文 需要第三方类库对中文进行分词 如pangu分词
//提供分词算法,可以把文档中的数据按照算法分词
//五、IndexWriterConfig(索引写出器配置类)
//1) 设置配置信息:Lucene的版本和分词器类型
//2)设置是否清空索引库中的数据
//六、IndexWriter(索引写出器类)
//索引写出工具,作用就是 实现对索引的增(创建索引)、删(删除索引)、改(修改索引)
//可以一次创建一个,也可以批量创建索引
//核心API
//5.2.2.1 QueryParser(查询解析器)
//1)QueryParser(单一字段的查询解析器)
//2)MultiFieldQueryParser(多字段的查询解析器)
//5.2.2.2 Query(查询对象,包含要查询的关键词信息)
//1)通过QueryParser解析关键字,得到查询对象
//2)自定义查询对象(高级查询)
//我们可以通过Query的子类,直接创建查询对象,实现高级查询(后面详细讲)
//5.2.2.3 IndexSearch(索引搜索对象,执行搜索功能)
//IndexSearch可以帮助我们实现:快速搜索、排序、打分等功能。
//IndexSearch需要依赖IndexReader类
//查询后得到的结果,就是打分排序后的前N名结果。N可以通过第2个参数来指定:
//5.2.2.4 TopDocs(查询结果对象)
//通过IndexSearcher对象,我们可以搜索,获取结果:TopDocs对象
//在TopDocs中,包含两部分信息:
//int totalHits :查询到的总条数
//ScoreDoc[] scoreDocs : 得分文档对象的数组
//5.2.2.5 ScoreDoc(得分文档对象)
//ScoreDoc是得分文档对象,包含两部分数据:
//int doc :文档的编号----lucene给文档的一个唯一编号
//float score :文档的得分信息
//拿到编号后,我们还需要根据编号来获取真正的文档信息
上代码:
1:接口:
public interface IDBService where TContext : Microsoft.EntityFrameworkCore.DbContext
{
TContext Context { get; }
}
//为泛型方法封装的。泛型方法里面实现的和搜索类实现的一样。
public interface IService
{
List QueryToList(int limit);
List QueryToList(int start, int end);
List QueryToList(string txt);
List QueryAll();
T QuerySignle(string guid);
T QuerySignle(int pk_id);
}
2:搜索类:
using System;
using System.Collections.Generic;
using System.Text;
using LuceneCore.Respority;
using LuceneCore.DB;
using Lucene.Net.Store;
using LuceneCore.Util;
using System.Linq;
namespace LuceneCore.Respority
{
class DbContextService : IDBService where TDbContext : Microsoft.EntityFrameworkCore.DbContext
{
public TDbContext Context { get; }
private List listType = new List();
//private static FSDirectory dir = FSDirectory.Open("");
private Lucene.Net.Index.IndexWriter writer = null;// new Lucene.Net.Index.IndexWriter(dir, new Lucene.Net.Analysis.PanGu.PanGuAnalyzer(), Lucene.Net.Index.IndexWriter.MaxFieldLength.LIMITED);
private Lucene.Net.Index.IndexReader reader = null;
public DbContextService(TDbContext _Context)
{
Context = _Context;
foreach (System.Reflection.PropertyInfo pro in Context.GetType().GetProperties())
{
if (pro.PropertyType.GenericTypeArguments != null && pro.PropertyType.GenericTypeArguments.Length > 0)
{
listType.Add(pro.PropertyType.GenericTypeArguments[0]);
}
}
}
public void Test(T t)
{
CreateIndexWriter(@"C:\Users\FanLin\Desktop\index");
var list = new List();
list.Add(t);
CreateIndex(list);
QueryByKeyWord("搜索", false, null, 100, null, "NAME");
var query1 = CreateQuery("搜索");
var query = CreateBooleanQuery((query1, Lucene.Net.Search.Occur.SHOULD));
QueryBySpecidQuery(query);
}
///
/// 创建IndexWriter和IndexReader对象
///
///
///
public (Lucene.Net.Index.IndexWriter, Lucene.Net.Index.IndexReader) CreateIndexWriter(string filePath)
{
FSDirectory dir = FSDirectory.Open(filePath);
if (writer == null)
{
writer = new Lucene.Net.Index.IndexWriter(dir, new Lucene.Net.Analysis.PanGu.PanGuAnalyzer(), Lucene.Net.Index.IndexWriter.MaxFieldLength.LIMITED);
writer.MergeFactor = 100;//控制多个segment合并的频率,默认10
writer.UseCompoundFile = true;//创建符合文件 减少索引文件数量
}
//var directory = System.IO.Directory.CreateDirectory(filePath);
if (reader == null)
{
reader = Lucene.Net.Index.IndexReader.Open(dir, false);
}
return (writer, reader);
}
///
/// 提交
///
private void CommitIndexWriter()
{
if (writer == null)
return;
writer.Commit();
}
//清除
private void FlushIndexWriter()
{
if (writer == null)
return;
writer.Flush(true, true, true);
}
///
/// 关闭
///
private void CloseIndexWriter()
{
if (writer == null)
return;
writer.Flush(true, true, true);
}
///
/// 创建索引
///
public void CreateIndex(IEnumerable tList)
{
// var config = new IndexWriterConfig(Lucene.Net.Util.LuceneVersion.LUCENE_48, _analyzer);
if (writer == null) return;
// 遍历实体集,添加到索引库
foreach (var entity in tList)
{
this.CreateIndex(entity);
}
this.CommitIndexWriter();
this.CloseIndexWriter();
}
///
/// 创建索引
///
private void CreateIndex(T tSignal)
{
if (writer == null) return;
if (writer.NumDocs() <= 0)
{
writer.AddDocument(tSignal.ToDocument());
}
else
{
this.UpdateIndex(tSignal);
}
//if (cmit) this.CommitIndexWriter(true);
}
///
/// 增加索引
///
private void UpdateIndex(T t)
{
if (writer == null) return;
if (reader == null) return;
//如果 有先删除
writer.UpdateDocument(new Lucene.Net.Index.Term(t.GetCustomAttributeColumn_KeyAndValue().field, t.GetCustomAttributeColumn_KeyAndValue().txt), t.ToDocument());
}
///
/// 批量修改索引
///
///
public void UpdateIndexEnumerable(IEnumerable ts)
{
//如果 有先删除
foreach (var t in ts)
{
UpdateIndex(t);
}
this.CommitIndexWriter();
this.CloseIndexWriter();
}
///
/// 删除索引
///
private void DeleteIndex(T t)
{
if (reader == null) return;
reader.DeleteDocuments(new Lucene.Net.Index.Term(t.GetCustomAttributeColumn_KeyAndValue().field, t.GetCustomAttributeColumn_KeyAndValue().txt));
}
///
/// 批量删除索引
///
public void DeleteIndex(IEnumerable tEnum)
{
if (reader == null) return;
foreach (var t in tEnum)
{
DeleteIndex(t);
}
this.CommitIndexWriter();
this.CloseIndexWriter();
}
///
/// 删除所有索引
///
public void DeleteAllIndex()
{
if (writer == null) return;
writer.DeleteAll();
}
///
/// 根据关键字来查询
///
/// 查询关键字
/// 是否对多字段查询
/// 过滤条件
/// 需要查出多少条
/// 排序规则
/// 对哪些字段做查询
///
public IEnumerable QueryByKeyWord(string keyWord, bool isMulti, Lucene.Net.Search.Filter filter, int n, Lucene.Net.Search.Sort sort, params string[] filterColumn)
{
// 索引搜索工具
//IndexSearch可以帮助我们实现:快速搜索、排序、打分等功能。
//IndexSearch需要依赖IndexReader类
Lucene.Net.Search.IndexSearcher searcher = new Lucene.Net.Search.IndexSearcher(reader);
//关键字
//string kwyWord = "";
Lucene.Net.Search.Query query = null;
//参数分别表示:版本号 对哪个字段分词查询 分词器
//这是对单一字段做分词查询
//单一字段查询 或者多个字段查询
if (isMulti && filterColumn.Length <= 1)
{
throw new ArgumentNullException(filter + "为null,请传入需要查询的字段");
}
if (!isMulti && filterColumn.Length > 1)
{
throw new ArgumentNullException(filter + "当前不是多字段查询,只允许传入一个字段名称!");
}
Lucene.Net.QueryParsers.QueryParser queryParser = null;
if (!isMulti)
{
//对单字段做查询
queryParser = new Lucene.Net.QueryParsers.QueryParser(Lucene.Net.Util.Version.LUCENE_30, filterColumn[0], new Lucene.Net.Analysis.PanGu.PanGuAnalyzer());
//解析关键字
// query = queryParser.Parse(keyWord);
}
else
{
queryParser = new Lucene.Net.QueryParsers.MultiFieldQueryParser(Lucene.Net.Util.Version.LUCENE_30, filterColumn, new Lucene.Net.Analysis.PanGu.PanGuAnalyzer());
}
//解析关键字
query = queryParser.Parse(keyWord);
//query的分类
//返回100条数据
// TopDocs(查询结果对象)
//通过IndexSearcher对象,我们可以搜索,获取结果:TopDocs对象
//是否需要过滤和排序
Lucene.Net.Search.TopDocs topDocs = searcher.Search(query, 100);
IList values = new List();
//ScoreDoc是得分文档对象
foreach (Lucene.Net.Search.ScoreDoc sDoc in topDocs.ScoreDocs)
{
float score = sDoc.Score;
//拿到document
Lucene.Net.Documents.Document document = reader.Document(sDoc.Doc);
values.Add(document.ToEntity());
//将document转换成entity
}
return values;
}
///
/// 根据query查询
///
///
private void QueryBySpecidQuery(Lucene.Net.Search.Query query)
{
// 索引搜索工具
//IndexSearch可以帮助我们实现:快速搜索、排序、打分等功能。
//IndexSearch需要依赖IndexReader类
if (query == null) return;
if (reader == null) return;
Lucene.Net.Search.IndexSearcher searcher = new Lucene.Net.Search.IndexSearcher(reader);
if (searcher == null) return;
//query的分类
//返回100条数据
// TopDocs(查询结果对象)
//通过IndexSearcher对象,我们可以搜索,获取结果:TopDocs对象
Lucene.Net.Search.TopDocs topDocs = searcher.Search(query, 100);
//ScoreDoc是得分文档对象
foreach (Lucene.Net.Search.ScoreDoc sDoc in topDocs.ScoreDocs)
{
int id = sDoc.Doc;
float score = sDoc.Score;
//拿到document
Lucene.Net.Documents.Document document = reader.Document(id);
//将document转换成entity
}
}
//TermQuery可以用“field:key”方式,例如“content:lucene”。
//BooleanQuery中‘与’用‘+’,‘或’用‘ ’,例如“content:java contenterl”。
//WildcardQuery仍然用‘?’和‘*’,例如“content:use*”。
//PhraseQuery用‘~’,例如“content:"中日"~5”。
//PrefixQuery用‘*’,例如“中*”。
//FuzzyQuery用‘~’,例如“content: wuzza ~”。
//RangeQuery用‘[]’或‘{}’,前者表示闭区间,后者表示开区间,例如“time:[20060101 TO 20060130]”,注意TO区分大小写。
//例如“标题或正文包括lucene,并且时间在20060101到20060130之间的文章” 可以表示为:“+ (title:lucene content:lucene) +time:[20060101 TO 20060130]”
/*
#region 特殊查询
///
/// 单条匹配查询
///
public void GetTermQuery(string content)
{
List fids = GetCustomAttributeForQuery();
if (fids != null && fids.Count() > 0)
{
Lucene.Net.Search.Query query = new Lucene.Net.Search.TermQuery(new Lucene.Net.Index.Term(fids[0], content));
}
}
///
/// 通配符查询
///
public void GetWildcardQuery(string charContent)
{
List fids = GetCustomAttributeForQuery();
if (fids != null && fids.Count() > 0)
{
Lucene.Net.Search.Query query = new Lucene.Net.Search.WildcardQuery(new Lucene.Net.Index.Term(fids[0], charContent));
}
//QueryLucene(query);
}
///
/// 模糊查询
///
public void GetFuzzyQuery(string content)
{
List fids = GetCustomAttributeForQuery();
if (fids != null && fids.Count() > 0)
{
Lucene.Net.Search.Query query = new Lucene.Net.Search.FuzzyQuery(new Lucene.Net.Index.Term(fids[0], content));
}
//QueryLucene(query);
}
///
/// 搜索两个单词距离指定间隔的数据
///
public void GetPhraseQuery(int slop, string prv, string next)
{
Lucene.Net.Search.PhraseQuery query = new Lucene.Net.Search.PhraseQuery();
query.Slop = 5;
query.Add(new Lucene.Net.Index.Term("content ", prv));
query.Add(new Lucene.Net.Index.Term("content", next));
}
///
/// 以指定字符开头
///
public void GetPrefixQuery(string content)
{
Lucene.Net.Search.PrefixQuery query = new Lucene.Net.Search.PrefixQuery(new Lucene.Net.Index.Term("content ", content));
}
#endregion
*/
///
/// 根据传入的特性查找定义了此特性的属性
///
///
///
private static List GetCustomAttributeForQuery()
{
var pro = typeof(T).GetProperties().Where(x => x.IsDefined(typeof(Attr), false));
var list = pro.Select(x => x?.Name).ToList();
return list;
// var prop=
//return typeof(T).GetProperties().Select(x =>
//{
// if (x.IsDefined(typeof(Attr), false))
// {
// return x.Name;
// }
// else
// {
// return null;
// }
//}).ToList();
}
///
/// 创建组合查询
///
/// 传入需要进行组合的查询方式和逻辑关联
///
public Lucene.Net.Search.Query CreateBooleanQuery(params (Lucene.Net.Search.Query query, Lucene.Net.Search.Occur occur)[] querysAndoccurs)
{
//Lucene.Net.Search.Query query = new Lucene.Net.Search.FuzzyQuery(new Lucene.Net.Index.Term("", ""));
//Lucene.Net.Search.Query query2 = Lucene.Net.Search.NumericRangeQuery.NewLongRange("", 0, 0, true, true);
Lucene.Net.Search.BooleanQuery bQuery = new Lucene.Net.Search.BooleanQuery();
//* 交集:Occur.MUST + Occur.MUST
//* 并集:Occur.SHOULD + Occur.SHOULD
//* 非:Occur.MUST_NOT
querysAndoccurs.ToList().ForEach(tuple =>
{
bQuery.Add(tuple.query, tuple.occur);
});
return bQuery;
}
///
/// 创建指定的查询方式。只支持单个查询。
///
/// 继承自Query的查询类。如WildcardQuery/PrefixQuery/FuzzyQuery/TermQuery四种等
/// 实体属性上定义的特性名称,表示其需要执行那种查询方式,若有多个则组合成组合查询
/// 查询关键字
///
public Lucene.Net.Search.Query CreateQuery(string content) where U : Lucene.Net.Search.Query where Attr : Util.Attributes.SpecidQueryAttribute
{
var tp = typeof(U);
var name = tp.Name;
//Lucene.Net.Search.Query query1 = new Lucene.Net.Search.TermQuery(new Lucene.Net.Index.Term("", ""));
switch (name)
{
case "WildcardQuery":
case "PrefixQuery":
case "FuzzyQuery":
case "TermQuery":
return Activator.CreateInstance(typeof(U), new Lucene.Net.Index.Term(GetCustomAttributeForQuery()[0], content)) as Lucene.Net.Search.Query;
}
throw new KeyNotFoundException("传入的泛型不正确");
}
///
/// 范围查询,包括数字范围或者查询两个字符串指定间隔的数据
///
///
/// U为long/int/float/double时传入数字,表示范围,为string时传入前边的字符串
/// U为long/int/float/double时传入数字,表示范围,为string时传入后边的字符串
/// U为string时传入前后的字符串,这个为两个字符串之间的间隔
///
public Lucene.Net.Search.Query CreateQuery(U minOrprv, U maxOrnext, int whenString = 0)
{
Lucene.Net.Search.Query query = null;
List fids = GetCustomAttributeForQuery();
if (fids != null && fids.Count() > 0)
{
switch (typeof(U).Name)
{
case "long":
case "Int64":
query = Lucene.Net.Search.NumericRangeQuery.NewLongRange(fids[0], long.Parse(minOrprv.ToString()), long.Parse(maxOrnext.ToString()), true, true);
break;
case "int":
case "Int32":
query = Lucene.Net.Search.NumericRangeQuery.NewIntRange(fids[0], int.Parse(minOrprv.ToString()), int.Parse(maxOrnext.ToString()), true, true);
break;
case "double":
query = Lucene.Net.Search.NumericRangeQuery.NewDoubleRange(fids[0], double.Parse(minOrprv.ToString()), double.Parse(maxOrnext.ToString()), true, true);
break;
case "float":
query = Lucene.Net.Search.NumericRangeQuery.NewFloatRange(fids[0], float.Parse(minOrprv.ToString()), float.Parse(maxOrnext.ToString()), true, true);
break;
case "string":
var pQuery = new Lucene.Net.Search.PhraseQuery();
pQuery.Slop = whenString;
pQuery.Add(new Lucene.Net.Index.Term(fids[0], minOrprv.ToString()));
pQuery.Add(new Lucene.Net.Index.Term(fids[0], maxOrnext.ToString()));
query = pQuery;
// query = new Lucene.Net.Search.MultiPhraseQuery();
break;
default:
//不允许的
throw new InvalidProgramException("传入参数有误,仅允许Long/Float/Double/Int/String");
}
}
return query;
}
///
/// 排序方式,如果要使用,需要添加SpecdSortAttribute
///
///
///
public Lucene.Net.Search.Sort SetSort(T t)
{
//需要拿字段和类型
//排序
Lucene.Net.Search.Sort sort = new Lucene.Net.Search.Sort(t.GetSortAttributeValue());//排序 哪个前哪个后
return sort;
}
///
/// 过滤条件
///
///
public Lucene.Net.Search.Filter SetFilter()
{
// Lucene.Net.Search.filter
return Lucene.Net.Search.NumericRangeFilter.NewIntRange("time", 20220112, 20220113, true, true);
}
}
}
3:扩展方法
public static class ModelExtison
{
///
/// 将实体转换成Document
///
///
///
///
public static Lucene.Net.Documents.Document ToDocument(this T t)
{
Lucene.Net.Documents.Document doc = new Lucene.Net.Documents.Document();
foreach (var propertyInfo in t.GetType().GetProperties())
{
var attr = propertyInfo.GetCustomAttributes(typeof(LuceneCore.Util.Attributes.LuceneDefineAttribute), false);
if (attr != null)
{
if (attr.Length > 0)
{
foreach (LuceneCore.Util.Attributes.LuceneDefineAttribute customAttr in attr)
{
doc.Add(new Lucene.Net.Documents.Field(propertyInfo.Name, propertyInfo.GetValue(t) == null ? "" : propertyInfo.GetValue(t).ToString(), customAttr.Store, customAttr.Index));
}
}
else
{
var attrtmp = new LuceneCore.Util.Attributes.LuceneDefineAttribute();
doc.Add(new Lucene.Net.Documents.Field(propertyInfo.Name, propertyInfo.GetValue(t) == null ? "" : propertyInfo.GetValue(t).ToString(), attrtmp.Store, attrtmp.Index));
}
}
}
return doc;
}
///
/// 将document转换为实体
///
///
///
///
public static T ToEntity(this Lucene.Net.Documents.Document document)
{
T t = default(T);
t = (T)Activator.CreateInstance(typeof(T));
foreach (System.Reflection.PropertyInfo pro in typeof(T).GetProperties())
{
pro.SetValue(t, Convert.ChangeType(document.Get(pro.Name), pro.PropertyType));
}
return t;
}
///
/// 返回标注了指定特性的字段和值
///
///
///
///
///
public static (string field, string txt) GetCustomAttributeColumn_KeyAndValue(this T obj)
{
foreach (System.Reflection.PropertyInfo pro in typeof(T).GetProperties())
{
if (pro.IsDefined(typeof(Attr), false))
{
var val = pro.GetValue(pro.Name);
return (pro.Name, val == null ? "" : val.ToString());
}
}
return ("", "");
}
///
/// 根据标注了排序特性的字段的类型返回排序类型
///
///
///
///
public static Lucene.Net.Search.SortField[] GetSortAttributeValue(this T obj)
{
Lucene.Net.Search.SortField[] tuples = null;
Dictionary keyValuePairs = new Dictionary();
var defindSpecidAttr = typeof(T).GetProperties().Where(x => x.IsDefined(typeof(Util.Attributes.SpecidSortAttribute), true));
if (defindSpecidAttr != null && defindSpecidAttr.Count() > 0)
{
int index = 0;
foreach (var item in defindSpecidAttr)
{
var attr = (Util.Attributes.SpecidSortAttribute)item.GetCustomAttributes(false).FirstOrDefault(x => x.GetType() == typeof(Util.Attributes.SpecidSortAttribute));
Lucene.Net.Search.SortField sortField = new Lucene.Net.Search.SortField(item.Name, item.PropertyType.GetSortFieldType(), attr.Desc);//降序
keyValuePairs.Add(sortField, attr.Order);
tuples[index] = sortField;
index++;
}
}
tuples = keyValuePairs.OrderBy(x => x.Value).Select(x => x.Key).ToArray();
// tuples = tuples.OrderBy(x => x.Order);
return tuples;
}
///
/// 具体根据某一类型返回具体数值
///
///
///
public static int GetSortFieldType(this Type t)
{
return t switch
{
_ when t.Name == "Int32" || t.Name == "int" => Lucene.Net.Search.SortField.INT,
_ when t.Name == "Int64" || t.Name == "long" => Lucene.Net.Search.SortField.LONG,
_ when t.Name == "float" => Lucene.Net.Search.SortField.FLOAT,
_ when t.Name == "double" => Lucene.Net.Search.SortField.DOUBLE,
_ when t.Name == "string" => Lucene.Net.Search.SortField.STRING,
_ when t.Name == "byte" => Lucene.Net.Search.SortField.BYTE,
_ when t.Name == "short" || t.Name == "Int16" => Lucene.Net.Search.SortField.SHORT,
_ => -1
};
}
public static void GetString(this object t)
{
Console.WriteLine(typeof(T).Name);
}
}
4:特性
4.1(有具体实现)
//Lucene标注特性
[AttributeUsage(AttributeTargets.Property)]
class LuceneDefineAttribute : Attribute
{
public LuceneDefineAttribute()
{
Store = Lucene.Net.Documents.Field.Store.YES;
Index = Lucene.Net.Documents.Field.Index.ANALYZED;
}
public Lucene.Net.Documents.Field.Store Store { get; set; }
public Lucene.Net.Documents.Field.Index Index { get; set; }
}
//排序特性
[System.AttributeUsage(System.AttributeTargets.Property)]
internal class SpecidSortAttribute : System.Attribute
{
public SpecidSortAttribute()
{
Desc = true;
Order = 0;
}
public bool Desc { get; set; }
public int Order { get; set; }
}
4.2(无具体实现,只是标注一下有便于反射时使用)
public class SpecidQueryAttribute : Attribute
{
}
public class TermQueryAttribute : SpecidQueryAttribute
{
}
public class WildcardQueryAttribute : SpecidQueryAttribute
{
}
public class FuzzyQueryAttribute : SpecidQueryAttribute
{
}
public class NumericRangeQueryAttribute : SpecidQueryAttribute
{
}
public class PhraseQueryAttribute : SpecidQueryAttribute
{
}
public class PrefixQueryAttribute : SpecidQueryAttribute
{
}
class SpecidFilterAttribute:Attribute
{
}
使用:
public void Test(T t)
{
CreateIndexWriter(@"C:\Users\FanLin\Desktop\index");
var list = new List();
list.Add(t);
CreateIndex(list);
QueryByKeyWord("搜索", false, null, 100, null, "NAME");
var query1 = CreateQuery("搜索");
var query = CreateBooleanQuery((query1, Lucene.Net.Search.Occur.SHOULD));
QueryBySpecidQuery(query);
}
总结:对Lucene一个简单的封装,也让自己了解一下,虽然平时用不到。而且还有什么比抄代码更快乐的呢
本来想把DContext注入进去,使T通用,但是目前能力有限还没有找到好方法。就只能使用泛型了。
参考文档:
http://www.luofenming.com/show.aspx?id=ART2021110700001
https://blog.csdn.net/qq_21137441/article/details/98941178