Lucene创建和搜索
来源:互联网 发布:最新3d公式计算法大全 编辑:程序博客网 时间:2024/04/29 22:17
Lucene的基本原理就是:先到数据库中取文章,创建索引文件,然后根据关键词到索引文件中取匹配的文章。
本文就先从创建索引开始:
我是直接创建一个控制台来跑的,然后调用一个线程,开始跑文章;我就直接从跑文章开始了:
文章数量太多了,所以我采用了一次跑10000篇文章的方式:
public string Dojob()
{
try
{
int min = GetMinId();//数据库获取最小ID
int max = GetMaxId();//数据库获取最大ID
string returnstr = "";
for (int i = min; i < max; i += 10000)
{
returnstr = returnstr + "\r\n" + CreatIndex(i);
}
return returnstr;
}
catch (Exception ex)
{
return ex.ToString();
}
}
return indexts.ToString();
}
public string CreatIndex(int i)
{
TimeSpan indexts = new TimeSpan();
try
{
DateTime starttime = DateTime.Now;
//创建字典,打开索引文件的存储位置,为写文章做准备
Lucene.Net.Store.FSDirectory directory = Lucene.Net.Store.FSDirectory.Open(new System.IO.DirectoryInfo(INDEX_STORE_PATH), new NativeFSLockFactory());
//IndexReader:对索引库进行读取的类
bool isExist = IndexReader.IndexExists(directory); //是否存在索引库文件夹以及索引库特征文件
if (isExist)
{
//如果索引目录被锁定(比如索引过程中程序异常退出或另一进程在操作索引库),则解锁
//Q:存在问题 如果一个用户正在对索引库写操作 此时是上锁的 而另一个用户过来操作时 将锁解开了 于是产生冲突 --解决方法后续
if (IndexWriter.IsLocked(directory))
{
IndexWriter.Unlock(directory);
}
}
//创建向索引库写操作对象 IndexWriter(索引目录,指定使用盘古分词进行切词,最大写入长度限制)
//补充:使用IndexWriter打开directory时会自动对索引库文件上锁//相当于创建一支写的笔和写在哪里
IndexWriter writer = new IndexWriter(directory, new PanGuAnalyzer(), !isExist, IndexWriter.MaxFieldLength.UNLIMITED);
var strList = this.GetArticles(i);//根据i到数据库取ID为(i-1)*10000到i*10000之间的文章
foreach (var book in strList)
{
Document document = new Document(); //new一篇文档对象 --一条记录对应索引库中的一个文档
////向文档中添加字段 Add(字段,值,是否保存字段原始值,是否针对该列创建索引)
document.Add(new Field("content", book, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
writer.AddDocument(document); //文档写入索引库
}
writer.Close();//会自动解锁
directory.Close(); //不要忘了Close,否则索引结果搜不到
DateTime endttime = DateTime.Now;
indexts = endttime - starttime;
}
catch (Exception ex)
{
return ex.ToString();
}
}
掺杂一些数据库的处理,生成索引库就完成了,下面根据关键词来进行文章匹配。
public string GetBestAricle(string keystr)
{
string fangfang = "";
ReturnArticle result = new ReturnArticle();
string Beststr = ""; //文章,这个字符串会包含一些我需要的文章id,文章标题等等信息,在建索引的时候包含进去
try
{
DateTime starttime = DateTime.Now;
//打开索引文件所在目录
FSDirectory directory = FSDirectory.Open(new System.IO.DirectoryInfo(INDEX_STORE_PATH), new NoLockFactory());
IndexReader reader = IndexReader.Open(directory, false);
IndexSearcher searcher = new IndexSearcher(reader);
//搜索条件
BooleanQuery query=new BooleanQuery();
//把用户输入的关键字进行分词
var KeyList = SplitWords(keystr);
string str = "";
for (int i=0;i<KeyList.Length;i++)
{
Query query1 = new TermQuery(new Term("content", KeyList[i]));
if (i == 0)
{
query.Add(query1, BooleanClause.Occur.MUST);
str = str + KeyList[i];
}
else
{//这里存在一个关键点,如果分词存在两个相同或者包含的词的话,文章匹配结果基本上没有任何作用
if (!str.Contains(KeyList[i]))
{
query.Add(query1, BooleanClause.Occur.MUST_NOT);
str = str + KeyList[i];
}
}
}
TopScoreDocCollector collector = TopScoreDocCollector.create(1000, true);
searcher.Search(query, null, collector);//根据query查询条件进行查询,查询结果放入collector容器
//TopDocs 指定0到GetTotalHits() 即所有查询结果中的文档 如果TopDocs(20,10)则意味着获取第20-30之间文档内容 达到分页的效果
ScoreDoc[] docs = collector.TopDocs(0, 50).scoreDocs;//collector.GetTotalHits()
//Beststr = docs[0].Get("content");
for (int i = 0; i < docs.Length; i++)
{
int docId = docs[i].doc;//得到查询结果文档的id(Lucene内部分配的id)
Document doc = searcher.Doc(docId);//根据文档id来获得文档对象Document
//book.ContentDescription = doc.Get("content");//未使用高亮
//搜索关键字高亮显示 使用盘古提供高亮插件
Beststr = doc.Get("content");
string[] mostr = Beststr.Split('@');//以@作为分隔符
fangfang += mostr[0].ToString();
if (Beststr.Length > 100)
{//取50个字符串数据库模糊查询,如果存在跳下一条,否则继续
string word = Beststr.Substring(20,70);
if (IsRepeat(word))
break;
reader.DeleteDocument(docId);
}
//后续写到数据库中
}
reader.Close();
}
catch (Exception ex)
{
throw (ex);
}
return Beststr;
}
public static string[] SplitWords(string content)
{
StringReader sb = new StringReader(content);
List<string> strList = new List<string>();
Analyzer analyzer = new PanGuAnalyzer(); ;//指定使用盘古 PanGuAnalyzer 分词算法
TokenStream tokenStream = analyzer.TokenStream("", sb);
Lucene.Net.Analysis.Token token = null;
// bool hasNext = tokenStream.IncrementToken();
while ((token = tokenStream.Next()) != null)
//while(hasNext)
{ //Next继续分词 直至返回null
// token =tokenStream.GetAttribute<Lucene.Net.Analysis.Tokenattributes.ITermAttribute>();;
strList.Add(token.TermText()); //得到分词后结果
// hasNext = tokenStream.IncrementToken();
}
return strList.ToArray();
}
- Lucene创建和搜索
- Lucene 入门之创建索引和搜索
- lucene创建索引初步和搜索初步
- Lucene创建索引和搜索索引
- lucene--创建索引,搜索
- Lucene-索引创建&搜索
- Lucene--002创建搜索
- Lucene介绍和创建索引和搜索初步
- Lucene简介和简单使用搜索和创建索引
- lucene 4.3 索引的简单创建和搜索代码展示
- 搜索引擎系列 -lucene简介 创建索引和搜索初步步骤
- 01-lucene简介和索引创建以及搜索
- Lucene创建索引及搜索
- 【Lucene&&Solr】Lucene索引和搜索流程
- Lucene和 搜索结果聚集
- Lucene 建立索引和搜索
- Lucene 索引和搜索过程
- lucene学习--创建索引与搜索
- IOS 改变提示placeholder颜色和大小
- EXXXUI盒子
- “//”与“\\”还有“/”与“\" 的区别
- java 编程思想 笔记摘录
- 你为什么要做产品经理
- Lucene创建和搜索
- 电池不准,重新校验.
- self.navigationItem和self.navigationController.navigationItem的区别?
- xUtils3.0使用介绍:注解模块
- mybatis配置文件
- Leetcode-76 Minimum Window Substring
- 从八皇后问题到回溯法
- 浙江省第四届“知识产权杯”创意设计大赛
- Rolling patch与Minimum downtime以及All-Node Patch解释(mos 244241.1)