热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

lucene.net学习六——多Field多索引文件的查询

在实际的需求中,我们需要输入一个关键语句,希望能搜索到标题中含有此关键词或者内容中也还有此关键语句的文章,这就是一个多Field查询的问题当然多Field之间的关系可能为“与”也有可能为“或”。一

在实际的需求中,我们需要输入一个关键语句,希望能搜索到标题中含有此关键词或者内容中也还有此关键语句的文章,这就是一个多Field查询的问题

当然多Field之间的关系可能为“与”也有可能为“或”。一般情况下,都在同一个目录索引下搜索,但是如果索引被分成很多文件,存在不同的地方,因此又会有一个多索引文件搜索的问题。下面通过代码演示:

首先编写建索引的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;
using Lucene.Net;
using Lucene.Net.Util;
using Lucene.Net.Store;
using Lucene.Net.Analysis;
using Lucene.Net.Index;
using Lucene.Net.Documents;

namespace TestIndexWriter
{
class Program
{
static void Main(string[] args)
{
//需要被索引的目录
FileInfo fi = new FileInfo(@"F:\doc");
//索引存放的路径
Lucene.Net.Store.Directory indexdir = FSDirectory.Open(new DirectoryInfo(@"F:\luceneindex1"));
//建立一个处理文本的分析器
Analyzer analyzer = new Lucene.Net.Analysis.Standard.StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29);
//创建索引写入器
IndexWriter writer = new IndexWriter(indexdir, analyzer, true, new IndexWriter.MaxFieldLength(10000));
//递归遍历指定目录下的所有的文件,并建立索引
IndexDocs(writer, fi);
Console.WriteLine("索引存放的目录为:F:\\luceneindex1");
writer.Close();
}

//遍历指定目录下的所有文件进行索引
private static void IndexDocs(IndexWriter writer, FileInfo file)
{
//判断指定的目录是否存在,注意不是文件的路径,C#中目录与文件的区别
//Directory.Exists()是判断指定的目录是否存在,而File.Exists()则是判断指定的文件是否存在
if (System.IO.Directory.Exists(file.FullName))
{
//获取指定目录中的所有文件和子目录
System.String[] files = System.IO.Directory.GetFileSystemEntries(file.FullName);
if (files != null)
{
for (int i = 0; i {
IndexDocs(writer, new System.IO.FileInfo(files[i]));//递归调用
}
}
}
//不是目录了,是文件,就开始加入索引
else
{
System.Console.WriteLine("开始索引文件: " + file.FullName);
try
{
Document d = new Document();
//对路径进行存储、索引但不分词
d.Add(new Field("path",file.FullName, Field.Store.YES, Field.Index.NOT_ANALYZED));
d.Add(new Field("contents", new StreamReader(file.FullName, System.Text.Encoding.Default)));
writer.AddDocument(d);
}
catch (System.IO.FileNotFoundException fnfe)
{
Console.WriteLine(fnfe.Message);
}
}
}
}
}

上面代码的意思是遍历目录F:\doc下的所有文件,并建立索引,建好后的索引存放在F:\luceneindex1下面。运行结果如下:

修改上面代码中的//需要被索引的目录
            FileInfo fi = new FileInfo(@"F:\doc1");
            //索引存放的路径
            Lucene.Net.Store.Directory indexdir = FSDirectory.Open(new DirectoryInfo(@"F:\luceneindex2"));

表示遍历目录F:\doc1下的所有文件,并建立索引,索引存放在F:\luceneindex2下,运行结果如下:

 

到此相当于生成了两个不同路径下的索引文件。

下面开始编写所Field多索引文件搜索的代码。

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;
using Lucene.Net;
using Lucene.Net.Search;
using Lucene.Net.Store;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Index;
using Lucene.Net.Documents;
using Lucene.Net.QueryParsers;

namespace MultiFieldMultiSearch
{
class Program
{
static void Main(string[] args)
{
//索引存放的路径1
Lucene.Net.Store.Directory indexdir1 = FSDirectory.Open(new DirectoryInfo(@"F:\luceneindex1"));
//初始化一个读索引器1
IndexSearcher IS1 = new IndexSearcher(indexdir1, true);

//索引存放的路径2
Lucene.Net.Store.Directory indexdir2 = FSDirectory.Open(new DirectoryInfo(@"F:\luceneindex2"));
//初始化一个读索引器2
IndexSearcher IS2 = new IndexSearcher(indexdir2, true);
//查询器数组
IndexSearcher[] searchers={IS1,IS2};
//构造一个多索引的查询器
MultiSearcher search = new MultiSearcher(searchers);

//2个需要查询的域名称
string[] fields={"filename","contents"};
//将每个域Field所查询的结果设为“或”的关系,也就是取并集
BooleanClause.Occur[] clauses={BooleanClause.Occur.SHOULD,BooleanClause.Occur.SHOULD};
//构造一个多Field查询
Query query = MultiFieldQueryParser.Parse(Lucene.Net.Util.Version.LUCENE_29, "郭靖", fields, clauses,
new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29));
Console.WriteLine(string.Format("查询条件为:{0}", query.ToString()));
Hits hits = search.Search(query);
for (int i = 0; i {
//更具文档的编号得到文档对象
Document doc = hits.Doc(i);
//根据给定的Filed名,得到对应的值
Console.WriteLine(doc.Get("path"));
//输出此文档的得分在结果集中
Console.WriteLine(hits.Score(i));
}
search.Close();
}
}
}

运行输出结果为:

 在代码里面输入"郭靖"作为查询词,根据lucene.net的标准分词方法,将“郭靖”分解为“郭”、“靖”这两个词,建索引的时候也是这样分解的,所以一定要保证建索引用的分词器与查询时用的分词器保持一致。

上面的查询条件的意思就是搜索包含郭或靖的文件名的文件,搜索包含郭或靖的内容的文件,两者的结果取并集

结果中还返回了每一个文件Document的打分

 


推荐阅读
  • Hadoop的文件操作位于包org.apache.hadoop.fs里面,能够进行新建、删除、修改等操作。比较重要的几个类:(1)Configurati ... [详细]
  • Spring – Bean Life Cycle
    Spring – Bean Life Cycle ... [详细]
  • 本文介绍如何使用 Python 的 DOM 和 SAX 方法解析 XML 文件,并通过示例展示了如何动态创建数据库表和处理大量数据的实时插入。 ... [详细]
  • 字节流(InputStream和OutputStream),字节流读写文件,字节流的缓冲区,字节缓冲流
    字节流抽象类InputStream和OutputStream是字节流的顶级父类所有的字节输入流都继承自InputStream,所有的输出流都继承子OutputStreamInput ... [详细]
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • 如果应用程序经常播放密集、急促而又短暂的音效(如游戏音效)那么使用MediaPlayer显得有些不太适合了。因为MediaPlayer存在如下缺点:1)延时时间较长,且资源占用率高 ... [详细]
  • IOS Run loop详解
    为什么80%的码农都做不了架构师?转自http:blog.csdn.netztp800201articledetails9240913感谢作者分享Objecti ... [详细]
  • 零拷贝技术是提高I/O性能的重要手段,常用于Java NIO、Netty、Kafka等框架中。本文将详细解析零拷贝技术的原理及其应用。 ... [详细]
  • oracle c3p0 dword 60,web_day10 dbcp c3p0 dbutils
    createdatabasemydbcharactersetutf8;alertdatabasemydbcharactersetutf8;1.自定义连接池为了不去经常创建连接和释放 ... [详细]
  • 在分析Android的Audio系统时,我们对mpAudioPolicy->get_input进行了详细探讨,发现其背后涉及的机制相当复杂。本文将详细介绍这一过程及其背后的实现细节。 ... [详细]
  • 在多线程并发环境中,普通变量的操作往往是线程不安全的。本文通过一个简单的例子,展示了如何使用 AtomicInteger 类及其核心的 CAS 无锁算法来保证线程安全。 ... [详细]
  • Java高并发与多线程(二):线程的实现方式详解
    本文将深入探讨Java中线程的三种主要实现方式,包括继承Thread类、实现Runnable接口和实现Callable接口,并分析它们之间的异同及其应用场景。 ... [详细]
  • JVM钩子函数的应用场景详解
    本文详细介绍了JVM钩子函数的多种应用场景,包括正常关闭、异常关闭和强制关闭。通过具体示例和代码演示,帮助读者更好地理解和应用这一机制。适合对Java编程和JVM有一定基础的开发者阅读。 ... [详细]
  • 本文详细介绍了 Pentaho Kettle 中 RowMetaInterface.writeMeta 方法的使用,并提供了多个代码示例,帮助开发者更好地理解和应用该方法。 ... [详细]
  • 在软件开发过程中,经常需要将多个项目或模块进行集成和调试,尤其是当项目依赖于第三方开源库(如Cordova、CocoaPods)时。本文介绍了如何在Xcode中高效地进行多项目联合调试,分享了一些实用的技巧和最佳实践,帮助开发者解决常见的调试难题,提高开发效率。 ... [详细]
author-avatar
qiuqiu
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有