idea怎么配置安装lucene安装配置搜索引擎

23.6k 人阅读
标签:至少1个,最多5个
一、配置项目
打开 project structure
配置【Project】
这里需要注意四个地方:1.项目名称,可以随便起。2.New一个jdk的安装路径。3.选一个6.0的接口。4.项目的classes路径。
【配置modules】
先配置Source。
点击“+”,可以增加项目。栏目中会出现项目,右侧也会出现项目。将光标移动到项目的src上,点击上面的source按钮,进行项目的src的添加,右边会显示出来的。
这里需要注意的就一个,配置项目的classes目录,提供输出的路径。
配置dependence。
这里加载的是jar包。点击右边的“+”。
1.jdk的路径。
2.项目lib路径。
3.添加Tomcat的jar包。要选library格式。(jsp-api.jar ,servlet-api.jar)
二、配置Tomcat
点击如图所示的地方,进行进入Tomcat配置页面。
添加tomcat应用服务器
如果找不到tomcat
到File-&Settings...添加
配置【server】
按照如图方式进行配置。 1代表名称,给配置的Tomcat取名称。
2代表配置Tomcat的安装路径。
3代表Tomcat服务器启动后,默认打开的浏览器,根据自己习惯打开。 4代表浏览器显示路径,根据自己喜好可以改。
5和6都是默认的,不需要修改。
配置【Deployment】
webapp为项目的webapp,后面的名字(应用的上下文路径)可以自己定义,别忘了加“/”.注意此处一定要选到WebContent文件夹,即WEB-INF上的上一级目录。
1 收藏&&|&&11
你可能感兴趣的文章
你可能感兴趣的文章
分享到微博?
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。记录一些东西
基于lucene搜索引擎的Hibernate Search,官方文档翻译
由于自己的项目需要用到搜索引擎,于是想到使用lucene,封装了lucene的框架有compass,solr,hibernate search.
网上对这些框架的描述有:
Compass:是在Lucene的基础上做了封装,支持索引事务控制和增量索引,同时也能够和主流的SSH框架完美地整合在一起,操作Compass类似于操作Hibernate,它们的类/方法等设计的非常相似。
项目主页:
该项目已经很久没有更新维护了,官方网站显示最后维护时间在
Solr:同样由Apache软件基金会提供和支持,基于Lucene的全文搜索服务器,采用Java5开发。同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化,并且提供了一个完善的功能管理界面,是一款非常优秀的全文搜索引擎。
Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引;也可以通过Http Get操作提出查找请求,并得到XML格式的返回结果
项目主页:
Hibernate Search:基于Lucene的基础上建立的主要用于Hibernate的持久化模型的全文检索工具。像Lucene这样的检索引擎能够给我们的项目在进行检索的时候带来非常高的效率,但是它们在基于对象的检索时会有一些问题,比如不能实现检索内容跟实体的转换,Hibernate Search正是在这样的情况下发展起来的,基于对象的检索引擎,能够很方便的将检索出来的内容转换为具体的POJO(实体对象)。此外Hibernate Search能够根据需要进行同步或异步的索引更新。
项目主页:
我的项目使用的开发语言是java,搭配ssh框架的j2ee应用。所以我选用hibernate search.方便快捷,开箱即用、
学习参考资料是通过官方的文档。
网上好像没有中文文档的翻译。找到了一个是3.3版本,别人翻译的。是从第4章开始翻译。
还搜到一个http://wiki.redsaga.com,但是不知道为什么不能访问,翻墙了也不行
现在已经是到4.2 Final,所以我从第一章开始边学边翻译吧。第4章以后就参考上面那个兄弟翻译的,综合自己的吧。
接下来我会不定期的更新翻译的章节...
有朋友觉得翻译不妥,需要更改的地方可以给我留言、
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!简单,踏实。
JavaWeb项目:整合(Lucene+Redis+SSM)实现搜索功能
整体思路:使用Redis做缓存,缓存策略为首次查询从数据库抓取,取出后存入Redis,删除和更新操作在Redis中进行,并且定时同步至数据库;Lucene做全文检索,RAMDirectory和FSDirectory并用,事先在磁盘生成索引,启动后转为RAMDirectory,存取均在RAMDirectory进行,采用“定时从RAMDirectory向磁盘同步”的策略。
Redis部分:
Redis工具类
public class RedisManager {
@Autowired
private ArticleMapper articleM
@Autowired
private RedisTemplate&String,Object& redisT
public Article getArticle(Long id){
if(id == null){
return null;
ValueOperations&String, Object& valueOper = redisTemplate.opsForValue();
Object value = valueOper.get("article:"+id);
if(value == null||!(value instanceof Article)){
return null;
return (Article)value;
public void setArticle(Long id,Article value){
if(id == null||value == null){
ValueOperations& String, Object& valueOper = redisTemplate.opsForValue();
valueOper.set( "article:"+String.valueOf(id) , value , 48 , TimeUnit.HOURS);
public void delArticle(Long id){
redisTemplate.delete("article:"+String.valueOf(id));
public void addDelKey(Long id){
ListOperations&String, Object& listOper = redisTemplate.opsForList();
listOper.rightPush("to_delete_keys", "article:"+String.valueOf(id));
public boolean isDeletedKey(Long id) {
ListOperations&String, Object& listOper = redisTemplate.opsForList();
List keys = listOper.range("to_delete_keys", 0, -1);
if(keys.contains("article:"+String.valueOf(id))){
return true;
return false;
public void addUpdateKey(Long id){
ListOperations&String, Object& listOper = redisTemplate.opsForList();
listOper.rightPush("to_update_keys", "article:"+String.valueOf(id));
public void redisSync(){
ValueOperations&String, Object& valueOper = redisTemplate.opsForValue();
ListOperations&String, Object& listOper = redisTemplate.opsForList();
List keys = listOper.range("to_update_keys", 0, -1);
Iterator iterator = keys.iterator();
while (iterator.hasNext()) {
String key = (String)iterator.next();
Article article =(Article)valueOper.get(key);
articleMapper.updateArticle(article);
redisTemplate.delete("to_update_keys");
keys = listOper.range("to_delete_keys", 0, -1);
iterator = keys.iterator();
while (iterator.hasNext()) {
String key = (String)iterator.next();
articleMapper.deleteArticle(Long.parseLong(key.split(":")[1]));
redisTemplate.delete("to_delete_keys");
System.out.println("-----redis同步完成------");
相关业务逻辑
public Article findArticleById(Long id) {
if(redisManager.isDeletedKey(id)){
return null;
Article article = redisManager.getArticle(id);
if(article == null){
article = articleMapper.findArticleById(id);
redisManager.setArticle(id, article);
System.out.println("------数据库中取出!");
删除数据 :
public void deleteArticle(Long id) {
redisManager.delArticle(id);
luceneManager.deleteDocument(id);
redisManager.addDelKey(id);
} catch (Exception e) {
e.printStackTrace();
更新数据 :
public void updateArticle(Article article) {
redisManager.setArticle(article.getId(), article);
luceneManager.updateDocument(article);
redisManager.addUpdateKey(article.getId());
} catch (Exception e) {
e.printStackTrace();
添加数据时不经过缓存:
public void addArticle(Article article) {
articleMapper.addArticle(article);
luceneManager.addDocument(article);
redisManager.setArticle(article.getId(), article);
} catch (Exception e) {
e.printStackTrace();
Lucene部分
Lucene工具类
public class LuceneUtil {
private static final String INDEXPATH="D:\\lucene";
private static RAMDirectory ramD
private static IndexWriter ramW
@Autowired
private ArticleMapper articleM
FSDirectory fsDirectory = FSDirectory.open(Paths.get(INDEXPATH));
ramDirectory = new RAMDirectory(fsDirectory,IOContext.READONCE);
fsDirectory.close();
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(
new SmartChineseAnalyzer());
indexWriterConfig.setIndexDeletionPolicy(
new SnapshotDeletionPolicy(new KeepOnlyLastCommitDeletionPolicy()));
ramWriter = new IndexWriter(ramDirectory, indexWriterConfig);
} catch (IOException e) {
e.printStackTrace();
public void reCreatIndex(){
Path path = Paths.get(INDEXPATH);
for (File file : path.toFile().listFiles()) {
file.delete();
FSDirectory fsDirectory = FSDirectory.open(path);
Analyzer analyzer = new SmartChineseAnalyzer();
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
IndexWriter writer = new IndexWriter(fsDirectory, indexWriterConfig);
List&Article& articles = articleMapper.findAll();
for (Article article : articles) {
writer.addDocument(toDocument(article));
writer.close();
System.out.println("-----创建索引成功---");
} catch (Exception e) {
e.printStackTrace();
public Document toDocument(Article article){
Document doc = new Document();
doc.add(new StringField("id",String.valueOf(article.getId()),Field.Store.YES));
doc.add(new Field("title", article.getTitle(), TextField.TYPE_STORED));
doc.add(new Field("details", article.getDetails(),TextField.TYPE_STORED));
public synchronized void addDocument(Article article) throws IOException{
ramWriter.addDocument(toDocument(article));
ramWriter.commit();
public synchronized void deleteDocument(Long id) throws IOException{
Term term = new Term("id",String.valueOf(id));
ramWriter.deleteDocuments(term);
ramWriter.commit();
public List&Article& search(String keyword) throws IOException, ParseException, InvalidTokenOffsetsException{
List&Article& list = new ArrayList&Article&();
IndexSearcher indexSearcher = new IndexSearcher(DirectoryReader.open(ramDirectory));
String [] fields = {"title","details"};
Analyzer analyzer = new SmartChineseAnalyzer();
QueryParser queryParser = new MultiFieldQueryParser(fields, analyzer);
Query query = queryParser.parse(keyword);
TopDocs hits = indexSearcher.search(query, 20);
SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("&b&&font color='red'&","&/font&&/b&");
Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(query));
for(ScoreDoc scoreDoc:hits.scoreDocs){
Article article = new Article();
Document doc = indexSearcher.doc(scoreDoc.doc);
article.setId(Long.valueOf(doc.get("id")));
String title = doc.get("title");
String details = doc.get("details");
article.setTitle(highlighter.getBestFragment(analyzer.tokenStream("title", new StringReader(title)), title));
article.setDetails(highlighter.getBestFragment(analyzer.tokenStream("details", new StringReader(details)), details));
list.add(article);
public void updateDocument(Article article) throws IOException{
Term term = new Term("id",String.valueOf(article.getId()));
ramWriter.updateDocument(term, toDocument(article));
ramWriter.commit();
public void indexSync(){
IndexWriterConfig config = null;
SnapshotDeletionPolicy snapshotDeletionPolicy = null;
IndexCommit indexCommit = null;
config = (IndexWriterConfig) ramWriter.getConfig();
snapshotDeletionPolicy = (SnapshotDeletionPolicy) config.getIndexDeletionPolicy();
indexCommit = snapshotDeletionPolicy.snapshot();
config.setIndexCommit(indexCommit);
Collection&String& fileNames = indexCommit.getFileNames();
Path toPath = Paths.get(INDEXPATH);
Directory toDir = FSDirectory.open(toPath);
for (File file : toPath.toFile().listFiles()) {
file.delete();
for (String fileName : fileNames) {
toDir.copyFrom(ramDirectory, fileName, fileName, IOContext.DEFAULT);
toDir.close();
} catch (Exception e) {
e.printStackTrace();
System.out.println("-----索引同步完成------");
Spring配置文件
&?xml version="1.0" encoding="UTF-8"?&
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"&
location="classpath*:properties/*.properties"/&
id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"&
name="maxIdle" value="${redis.maxIdle}"/&
name="maxWaitMillis" value="${redis.maxWait}"/&
name="testOnBorrow" value="${redis.testOnBorrow}"/&
id="connectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"&
name="poolConfig" ref="poolConfig"/&
name="hostName" value="${redis.host}"/&
name="port" value="${redis.port}"/&
name="password" value="${redis.auth}"/&
name="timeout" value="${redis.timeout}"/&
id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"&
name="connectionFactory" ref="connectionFactory" /&
name="keySerializer" &
class="org.springframework.data.redis.serializer.StringRedisSerializer" /&
name="valueSerializer" &
class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" /&
id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"&
name="driverClassName" value="${mysql.driver}"/&
name="url" value="${mysql.url}"/&
name="username" value="${mysql.user}"/&
name="password" value="${mysql.password}"/&
name="initialSize" value="${druid.initialSize}"/&
name="minIdle" value="${druid.minIdle}"/&
name="maxActive" value="${druid.maxActive}"/&
name="maxWait" value="${druid.maxWait}"/&
id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"&
name="dataSource" ref="dataSource" /&
name="configLocation" value="classpath:config/mybatis-config.xml" /&
class="org.mybatis.spring.mapper.MapperScannerConfigurer"&
name="basePackage" value="com.search.mapper" /&
name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /&
base-package="com.search.service"/&
id="redisManager" class="com.search.utils.RedisManager"/&
id="luceneManager" class="com.search.utils.LuceneUtil"/&
id="redisSync" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"&
name="targetObject" ref="redisManager"/&
name="targetMethod" value="redisSync"/&
id="redisTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"&
name="jobDetail" ref="redisSync" /&
name="cronExpression" value="0 0 0 * * ?" /&
id="indexSync" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"&
name="targetObject" ref="luceneManager"/&
name="targetMethod" value="indexSync"/&
id="luceneTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"&
name="jobDetail" ref="indexSync" /&
name="startDelay" value="60000" /&
name="repeatInterval" value="7200000" /&
class="org.springframework.scheduling.quartz.SchedulerFactoryBean"&
name="triggers"&
bean="redisTrigger" /&
bean="luceneTrigger" /&
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!Engineers are versatile minds who create links between science, technology, and society.
scrapy+Lucene搭建小型搜索引擎(现代信息检索大作业)
工程类搜索型:
定向采集 3-4 个新闻网站, 实现这些网站信息的抽取、索引和检索。网页数 目不少于 10 万条。能按相关度、时间、热度 (需要自己定义) 等属性进行排序, 能实现相似 新闻的自动聚类。
要求: 有相关搜索推荐、snippet 生成、结果预览 (鼠标移到相关结果, 能预览) 功能
二、开发工具
jdk 版本:1.7
服务器:Tomcat7.0
python:2.7
scrapy:1.0
三、设计方案
3.1整体思路
在实现新闻信息检索系统时首先进行了信息采集,信息采集结束之后使用 Lucene 提供的 api 构建索引库, 前端使用 jsp 接收用户查询,在后台使用 servlet 对用户查询进 行分词处理,之后到索引库中进行文档匹配, 最后把查询结果集反馈给用户并在前端页面中 展示。
3.2信息采集
Scrapy 是 Python 开发的一个快速、高层次的屏幕抓取和 web 抓取框架,用于抓取 web 站点并从页面中提取结构化的数据。我们采集了 10w+ 新闻数据, 新闻信息以 json 文件格 式保存。scrapy 采集流程:
采集到的新闻数据:
新闻格式:
3.3倒排索引构建
在索引构建模块,主要包括下面三个关键步骤: 数据预处理、新闻内容分词、构建倒排 索引。
**数据预处理:**Gson 是 Google 提供的用来在 Java 对象和 JSON 数据之间进行映射的 Java 类库。可以将一个 JSON 字符串转成一个 Java 对象, 或者反过来。我们使用 Gson 把 json 文件转换为 News 对象
**中文分词:**IK Analyzer 是一个开源的,基于 java 语言开发的轻量级的中文分词工具 包,IK 发展为面向 Java 的公用分词组件,独立于 Lucene 项目,同时提供了对 Lucene 的默 认优化实现。IK 分词采用了特有的“正向迭代最细粒度切分算法“, 支持细粒度和智能分词两 种切分模式, 并且采用了多子处理器分析模式, 支持英文字母、数字、中文词汇等分词处理, 兼容韩文、日文字符。
**构建倒排索引:**Lucene 提供了构建倒排索引的方法,步骤如下图所示:
Luke 是一个用于 Lucene 搜索引擎的,方便开发和诊断的第三方工具,它可以访问
现有 Lucene 的索引. 使用 luke 打开索引目录,可以看到新闻信息被存储到索引库中。
3.4索引查询
索引创建好以后,查询可分为以下几个步骤:
设置查询索引的目录 (这里就是上面创建索引的目录).
2. 创建 indexSearcher.
3. 设置 query 的分词方式
4. 设置查询域, 比如查询域为 news title, 那么就到新闻标题域去比对 5. 设置查询字符串,也就是要查询的关键词.
6. 返回结果是一个文档集合,放在 TopDocs 中,通过循环 TopDocs 数组输出查询结果. 用户一般只看前几页的数据,为了加快前端的数据展示, 返回前 1000 条数据到前台。
3.5关键字高亮
检索结果高亮对于用户的体验度和友好度非常重要,可以快速标记出用户检索对关键 词。Lucene 的 Highlighter 类可以用于返回文档中的关键字高亮,通过在关键字前面添加 css 片段来实现。
3.6用户界面
使用 jsp 编写用户界面,服务器为 Tomcat 7.0, 用户输入关键词以后提交表单,后
台使用 servlet 接收用户查询, 之后把查询字符串作为搜索的 key 到索引库中搜索文档。检索效果:
3.7按时间排序和结果分页
按时间排序: 所有的新闻结果存放在一个 list 集合中,集合中的每个元素为一个 News 对象, 通过重写 Comparator 类中的 compare 方法实现按集合中每个新闻元素的 Time 排 序。
结果分页: 定义了一个 Page 类用来记录当前页、总页数、每页多少条数据、总的数据 数、每页起始数、每页终止数、是否有下一页、是否有前一页。
四、参考资料
下面列出可参考的资料:
开源工具的使用显著提高了开 发效率,但build from ground还需要学习很多东西,继续沉淀。
欢迎批评指正。
扫码向博主提问
熟悉Lucene、ES、ELK
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!}

我要回帖

更多关于 开源搜索引擎lucene 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信