搜索引擎开发笔记二

本文详细介绍了如何使用Lucene为TXT文件建立索引,包括创建IndexProcessor类,利用createIndex方法处理文件并构建Document,以及LoadFileToString方法读取文件内容。建立的索引存储在D:indexr文件夹中,通过对比搜索功能类和直接字符串匹配,展示了索引搜索的高效性。然而,由于分词过程可能导致分词不准确,这可能会造成搜索结果的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       上回书说到已经为txt文件进行了简单的预处理,接下来就要开始建立索引了:)。  

       步骤:1.为要处理的内容建立索引    2.构建查询对象    3.在索引中查找

        首先我们要在firstProject的“firstPoject.lucene.process”包下创建一个IndexProcesser。

        代码如下

package firstProject.lucenedemo.process;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import jeasy.analysis.MMAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;

public class IndexProcesser {
	// 成员变量存储创建的索引文件存放的位置
	private String INDEX_STORE_PATH = "D:\\index";

	// 创建索引
	public void createIndex(String inputDir) {
		try {
			// MMAnalyzer作为分词工具创建一个IndexWriter
			IndexWriter writer = new IndexWriter(INDEX_STORE_PATH,
					new MMAnalyzer(), true);
			File filesDir = new File(inputDir);
			// 取得所有需要建立索引的文件数组
			File[] files = filesDir.listFiles();
			// 遍历数组
			for (int i = 0; i < files.length; i++) {
				// 获取文件名
				String fileName = files[i].getName();
				// 判断文件是否为txt类型的文件
				if (fileName.substring(fileName.lastIndexOf("."))
						.equals(".txt")) {
					// 创建一个新的Document
					Document doc = new Document();
					// 为文件名创建一个Field
					Field field = new Field("filename", files[i].getName(),
							Field.Store.YES, Field.Index.TOKENIZED);
					doc.add(field);
					// 为文件内容创建一个Filed
					field = new Field("content", loadFileToString(files[i]),
							Field.Store.NO, Field.Index.TOKENIZED);
					doc.add(field);
					// 把Document加入IndexWriter
					writer.addDocument(doc);
				}
			}
			// 关闭IndexWriter
			writer.close();

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public static void main(String[] args) {
		IndexProcesser processor = new IndexProcesser();
		processor.createIndex("D:\\TDDOWNLOAD\\niceFolder");
	}
	public String loadFileToString(File file) {
		try {
			BufferedReader br = new BufferedReader(new FileReader(file));
			StringBuffer sb = new StringBuffer();
			String line = br.readLine();
			while (line != null) {
				sb.append(line);
				line = br.readLine();
			}
			br.close();
			return sb.toString();
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

}


 

上述代码有两个方法

1.createIndex:该方法接受一个参数inputDir,该参数表示等待被建立索引的文件的存放路径。方法会从该路径中取出所有.txt文件,为每一个文件创建一个Lucene的Document文档,并向每个Document文档内加入了一些文件信息,包括文件名以及文件内容。可能你和我一样,现在对这些Document之类的术语朦胧着,不要紧,慢慢来。

2.LoadFileToString:在将文件内容加入到Document时,调用了类中另一个公有方法loadFileToString。它被用来从一个文件中读出其全部内容,并返回一个String类型的对象。该方法较简单,在BufferReader文件夹中,将每行的内容读取并装入StringBuffer中,最后一行返回。

        createIndex中使用了Lucene的API,将建立的Document对象加入到索引中去,也将文件名和文件内容等信息加入了Lucene的索引。


 

现在在查看D:\indexr文件夹就可以发现所有的文本文件建立了索引文本文件越大,.cfs文件越多  欧了,这样索引就建立成功了

 

接下来我们就要建立一个有搜索功能的类 (右键单击"firstProject.lucenedemo.process"->New->class->命名为Search)

代码如下

package firstProject.lucenedemo.process;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;

public class Search {
	
	private String INDEX_STORE_PATH = "D:\\index";

	public void indexSearch(String searchType, String searchKey) {
		try {
			// 根据索引位置建立IndexSearcher
			IndexSearcher searcher = new IndexSearcher(INDEX_STORE_PATH);
			// 建立搜索单元,searchType代表要搜索的Filed,searchKey代表关键字
			Term t = new Term(searchType, searchKey);
			// 由Term生成一个Query
			Query q = new TermQuery(t);
			// 搜索开始时间
			Date beginTime = new Date();
			// 获取一个<document, frequency>的枚举对象TermDocs
			TermDocs termDocs = searcher.getIndexReader().termDocs(t);
			while (termDocs.next()) {
				// 输出在文档中出现关键词的次数和搜索到关键词的文档
				System.out.println("find "+termDocs.freq()+" matches in "+searcher.getIndexReader().document(termDocs.doc()).getField("filename").stringValue());
			}
			// 搜索完成时间
			Date endTime = new Date();
			// 搜索所耗时间
			long timeOfSearch = endTime.getTime() - beginTime.getTime();
			System.out.println("The time For indexsearch is " + timeOfSearch + " ms");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void StringSearch(String keyword, String searchDir) {
		File filesDir = new File(searchDir);
		// 返回目录文件夹所有文件数组
		File[] files = filesDir.listFiles();
		// HashMap保存文件名和匹配次数对
		Map rs = new HashMap();
		// 记录搜索开始时间
		Date beginTime = new Date();
		// 遍历所有文件
		for (int i = 0; i < files.length; i++) {
			// 初始化匹配次数
			int hits = 0;
			try {
				// 读取文件内容
				BufferedReader br = new BufferedReader(new FileReader(files[i]));
				StringBuffer sb = new StringBuffer();
				String line = br.readLine();
				while (line != null) {
					sb.append(line);
					line = br.readLine();
				}
				br.close();
				// 将StringBuffer转化成String,以便于搜索
				String stringToSearch = sb.toString();
				// 初始化fromIndex
				int fromIndex = -keyword.length();
				// 逐个匹配关键词
				while ((fromIndex = stringToSearch.indexOf(keyword, fromIndex
						+ keyword.length())) != -1) {
					hits++;
				}
				// 将文件名和匹配次数加入HashMap
				rs.put(files[i].getName(), new Integer(hits));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		// 输出查询结果
		Iterator it = rs.keySet().iterator();
		while (it.hasNext()) {
			String fileName = (String) it.next();
			Integer hits = (Integer) rs.get(fileName);
			System.out.println("find " + hits.intValue() + " matches in "
					+ fileName);
		}
		// 记录结束时间
		Date endTime = new Date();
		// 得到搜索耗费时间
		long timeOfSearch = endTime.getTime() - beginTime.getTime();
		System.out.println("The time For string search is " + timeOfSearch + " ms");
	}

}


 

然后再从"first.lucene.test"中建立一个测试类 (右键单击“first.lucene.test"->New->class->命名为SearchTimeCompareTest)

代码如下

package firstProject.lucenedemo.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import firstProject.lucenedemo.process.Search;

public class SearchTimeCompareTest {
	public static void main(String[] args) {
		Search search = new Search();
		// 通过索引搜索关键词
		search.indexSearch("content", "她");
		//插入一个分隔行
		System.out.println();
		// 通过String的API搜索关键词
		search.StringSearch("她", "D:\\TDDOWNLOAD\\niceFolder");
	}

}


 

搜索结果

可以看出用索引来找几乎不用时间,而字符串匹配需要10ms。这只是个很小很小的txt,上兆呢?答案不言而喻。

但可以发现两者结果有差异,因为建立索引时,要先分词后建立索引,而分词过程中对于一些词的处理与我们理解的内容不太一样(语义偏差或二义),因此会出现分词不正确的情况。(摘自《开发自己的搜索引擎》人民邮电出版社)

《餐馆点餐管理系统——基于Java和MySQL的课程设计解析》 在信息技术日益发达的今天,餐饮行业的数字化管理已经成为一种趋势。本次课程设计的主题是“餐馆点餐管理系统”,它结合了编程语言Java和数据库管理系统MySQL,旨在帮助初学者理解如何构建一个实际的、具有基本功能的餐饮管理软件。下面,我们将深入探讨这个系统的实现细节及其所涉及的关键知识点。 我们要关注的是数据库设计。在“res_db.sql”文件中,我们可以看到数据库的结构,可能包括菜品表、订单表、顾客信息表等。在MySQL中,我们需要创建这些表格并定义相应的字段,如菜品ID、名称、价格、库存等。此外,还要设置主键、外键来保证数据的一致性和完整性。例如,菜品ID作为主键,确保每个菜品的唯一性;订单表中的顾客ID和菜品ID则作为外键,与顾客信息表和菜品表关联,形成数据间的联系。 接下来,我们来看Java部分。在这个系统中,Java主要负责前端界面的展示和后端逻辑的处理。使用Java Swing或JavaFX库可以创建用户友好的图形用户界面(GUI),让顾客能够方便地浏览菜单、下单。同时,Java还负责与MySQL数据库进行交互,通过JDBC(Java Database Connectivity)API实现数据的增删查改操作。在程序中,我们需要编写SQL语句,比如INSERT用于添加新的菜品信息,SELECT用于查询所有菜品,UPDATE用于更新菜品的价格,DELETE用于删除不再提供的菜品。 在系统设计中,我们还需要考虑一些关键功能的实现。例如,“新增菜品和价格”的功能,需要用户输入菜品信息,然后通过Java程序将这些信息存储到数据库中。在显示所有菜品的功能上,程序需要从数据库获取所有菜品数据,然后在界面上动态生成列表或者表格展示。同时,为了提高用户体验,可能还需要实现搜索和排序功能,允许用户根据菜品名称或价格进行筛选。 另外,安全性也是系统设计的重要一环。在连接数据库时,要避免SQL注入攻击,可以通过预编译的PreparedStatement对象来执行SQL命令。对于用户输入的数据,需要进行验证和过滤,防止非法字符和异常值。 这个“餐馆点餐管理系统”项目涵盖了Java编程、数据库设计与管理、用户界面设计等多个方面,是一个很好的学习实践平台。通过这个项目,初学者不仅可以提升编程技能,还能对数据库管理和软件工程有更深入的理解。在实际开发过程中,还会遇到调试、测试、优化等挑战,这些都是成长为专业开发者不可或缺的经验积累
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值