[lucene] Lucence 搜索技术
paladin00
2009-06-01
请教一个问题:
1.你已经实现的是对数据库中一张数据表建立的索引吗?还是多张表? 2.为了实现站内搜索,可以对一个网站中用到的多张业务表建立索引吗? |
|
ybzshizds
2009-06-01
apache开源博客项目roller的索引好像就是实时更新的,这个项目用了concurrent组件,可以通过锁机制避免并发冲突
public void run() { try { //ReadWriteLock rwl = new WriterPreferenceReadWriteLock(); manager.getReadWriteLock().writeLock().acquire(); mLogger.debug("Starting search index operation"); doRun(); mLogger.debug("Search index operation complete"); } catch (InterruptedException e) { mLogger.error("Error acquiring write lock on index", e); } finally { manager.getReadWriteLock().writeLock().release(); } manager.resetSharedReader(); } 子类去实现doRun()操作 |
|
lym6520
2009-06-01
paladin00 写道 请教一个问题:
1.你已经实现的是对数据库中一张数据表建立的索引吗?还是多张表? 2.为了实现站内搜索,可以对一个网站中用到的多张业务表建立索引吗? 你可以建立多个索引,然后根据不同的搜索类型查找搜索对应的索引文件 |
|
ybzshizds
2009-06-02
引用 你可以建立多个索引,然后根据不同的搜索类型查找搜索对应的索引文件
我觉得对多张表进行索引是不可取的,除非这些表之间是一点关联都没有,因为lucene不像关系数据库那样支持表之间的连接查询。否则就只有通过冗余字段去实现了,而且还是有一些麻烦,这里我举个我自己遇到的例子。 如有一培训机构发布自己的培训课程 一个培训机构可以发布多个培训课程,机构和课程之间是一对多的关系 public class TraOrganInfo{ private Integer traId; //培训机构ID private String userName; //用户名 private String passWord; //密码 private String traName; //培训机构名称 private String traIntroduction //培训机构简介 private String address; //地址 private String zipCode; //邮编 private Date registerDate; //在我们网站上的注册时间 private Date updateDate; //修改时间 private Date checkDate; //审核时间 private Short checkFlag=new Short("0"); //checkFlag 0:未审核 2:审核通过 3:审核不通过 ..........省略getter setter......... } 课程 public class TraCourse{ private Integer courseId; //课程ID private String courseType; //课程类别 private String courseTitle; //课程主题 private String courseContent; //课程内容 private String teacherName; //老师 private Date startDate; //开课时间 private Date endDate; //结束时间 private String trainPlace; //上课地点 private Date postDate; //发布时间 ..........省略getter setter......... } 搜索需求是 对培训机构的搜索:搜已经审核通过的,可以在培训机构名称traName和培训机构简介traIntroduction等字段中进行关键字搜索 对培训课程的搜索:搜索已经通过审核的机构发布的课程,可以在培训机构名称traName,课程主题courseTitle,课程内容courseContent等字段中进行关键字搜索。 这样一来问题就来了,因为lucene不支持连接查询,所以我必须通过冗余字段的方式去实现,于是在TraCourse类中加入两个冗余字段 private String traName; //培训机构名称 private Short checkFlag=new Short("0"); //checkFlag 0:未审核 2:审核通过 3:审核不通过 于是原来的TraCourse类就变成下面这样 public class TraCourse{ private Integer courseId; //课程ID private String courseType; //课程类别 private String courseTitle; //课程主题 private String courseContent; //课程内容 private String teacherName; //老师 private Date startDate; //开课时间 private Date endDate; //结束时间 private String trainPlace; //上课地点 private Date postDate; //发布时间 //加入两个冗余字段 private String traName; //培训机构名称 private Short checkFlag=new Short("0"); //checkFlag 0:未审核 2:审核通过 3:审核不通过 ..........省略getter setter......... } 好像搜索课程的需求也解决了,可是最后发现问题又来了,培训机构注册后,机构的名称还可以修改的。 那么当机构修改机构名称的时候,我还得去索引中找他所发布的课程,然后将课程索引中的字段traName全部改成新的培训机构的名词,如果一个机构已经发布了1000多个课程信息,突然要更改自己的机构名称,那就是说,在他修改培训机构名称的同时,我要修改1000笔和他相关的培训课程信息索引中的traName 另外还有一个问题是,一家培训机构注册后就可以发布自己的培训课程信息了,但是在没审核通过的时候,外面是搜索不到他所发布的课程的,一旦他被审核了,我也要去修改该机构所发布的所有课程信息索引中的审核标志checkFlag 仅仅两张表进行索引就这么麻烦,更不用说多张表了,所以我认为关联的多张表都做成索引的话,那牵扯出来的问题将是一大堆,lucene毕竟只是用来做全文索引的,如果能做多个索引之间的关联搜索的话,就可以取代数据库了,呵呵! |
|
lym6520
2009-06-03
ybzshizds 写道 引用 你可以建立多个索引,然后根据不同的搜索类型查找搜索对应的索引文件
我觉得对多张表进行索引是不可取的,除非这些表之间是一点关联都没有,因为lucene不像关系数据库那样支持表之间的连接查询。否则就只有通过冗余字段去实现了,而且还是有一些麻烦,这里我举个我自己遇到的例子。 如有一培训机构发布自己的培训课程 一个培训机构可以发布多个培训课程,机构和课程之间是一对多的关系 public class TraOrganInfo{ private Integer traId; //培训机构ID private String userName; //用户名 private String passWord; //密码 private String traName; //培训机构名称 private String traIntroduction //培训机构简介 private String address; //地址 private String zipCode; //邮编 private Date registerDate; //在我们网站上的注册时间 private Date updateDate; //修改时间 private Date checkDate; //审核时间 private Short checkFlag=new Short("0"); //checkFlag 0:未审核 2:审核通过 3:审核不通过 ..........省略getter setter......... } 课程 public class TraCourse{ private Integer courseId; //课程ID private String courseType; //课程类别 private String courseTitle; //课程主题 private String courseContent; //课程内容 private String teacherName; //老师 private Date startDate; //开课时间 private Date endDate; //结束时间 private String trainPlace; //上课地点 private Date postDate; //发布时间 ..........省略getter setter......... } 搜索需求是 对培训机构的搜索:搜已经审核通过的,可以在培训机构名称traName和培训机构简介traIntroduction等字段中进行关键字搜索 对培训课程的搜索:搜索已经通过审核的机构发布的课程,可以在培训机构名称traName,课程主题courseTitle,课程内容courseContent等字段中进行关键字搜索。 这样一来问题就来了,因为lucene不支持连接查询,所以我必须通过冗余字段的方式去实现,于是在TraCourse类中加入两个冗余字段 private String traName; //培训机构名称 private Short checkFlag=new Short("0"); //checkFlag 0:未审核 2:审核通过 3:审核不通过 于是原来的TraCourse类就变成下面这样 public class TraCourse{ private Integer courseId; //课程ID private String courseType; //课程类别 private String courseTitle; //课程主题 private String courseContent; //课程内容 private String teacherName; //老师 private Date startDate; //开课时间 private Date endDate; //结束时间 private String trainPlace; //上课地点 private Date postDate; //发布时间 //加入两个冗余字段 private String traName; //培训机构名称 private Short checkFlag=new Short("0"); //checkFlag 0:未审核 2:审核通过 3:审核不通过 ..........省略getter setter......... } 好像搜索课程的需求也解决了,可是最后发现问题又来了,培训机构注册后,机构的名称还可以修改的。 那么当机构修改机构名称的时候,我还得去索引中找他所发布的课程,然后将课程索引中的字段traName全部改成新的培训机构的名词,如果一个机构已经发布了1000多个课程信息,突然要更改自己的机构名称,那就是说,在他修改培训机构名称的同时,我要修改1000笔和他相关的培训课程信息索引中的traName 另外还有一个问题是,一家培训机构注册后就可以发布自己的培训课程信息了,但是在没审核通过的时候,外面是搜索不到他所发布的课程的,一旦他被审核了,我也要去修改该机构所发布的所有课程信息索引中的审核标志checkFlag 仅仅两张表进行索引就这么麻烦,更不用说多张表了,所以我认为关联的多张表都做成索引的话,那牵扯出来的问题将是一大堆,lucene毕竟只是用来做全文索引的,如果能做多个索引之间的关联搜索的话,就可以取代数据库了,呵呵! 你可以通过id将两个表关联起来,然后分别建立索引,查找时,相对索引文件进行查找,然后找到id再到数据库中取相关的数据,看这样行不行。 |
|
ybzshizds
2009-06-03
引用 你可以通过id将两个表关联起来,然后分别建立索引,查找时,相对索引文件进行查找,然后找到id再到数据库中取相关的数据,看这样行不行。
还是拿上面的例子说事,如果TraCourse(培训课程)类中不增加traName(培训机构名称)冗余字段,如何能实现对培训课程进行搜索时,可以根据培训机构的名称进行搜索。 比如:培训机构 新东方 发布了一个培训课程 商务英语 ,你要根据关键字“新东方”,搜索到 商务英语 这个培训课程,你不用冗余字段的方 法,如何实现这样的功能。 现在关键是搜索的问题(因为搜索是不能依靠数据库,只能来自于索引文件),而不是搜索后,查看课程具体信息的问题(可以拿到ID去数据库中进行关联查询)。 |
|
zxh116116
2009-07-13
lym6520 写道 对于Lucence搜索技术,早前几个月就已经接触过了,也看了不少资料,这周才用上这个了不起的搜索技术,做出来的效果更Google差不多,不过技术肯定没人家的好,主要是数据量不大,很适用,发两张效果图看看:
![]() ![]() 其实效果是达到了,不过性能还待优化,自然速度不会比Google的差,当然最主要的原因是我们数据量小。 呵,现在谈谈创建索引、增加索引、修改索引、删除索引时要注意的一些细节吧! 创建索引的时候我们要先声明一个IndexWriter对象,这时要注意了,实例化一个IndexWriter的时候需要三个参数,第一参数是索引存放的目录,第二个参数是解析器类型,最主要的是第三个参数create是布尔型的,当创建新索引时应当是true,当我们要修改、删除、添加索引时,应当要设成false,否则当你搜索的时候会出现“nDocs must be > 0”的错误,索引在对索引进行增、删、改的时候要特别小心。 IndexWriter writer = new IndexWriter(dir, getAnalyzer(),create); 现在说说怎么实现类似Google搜索效果吧! 要实现这样的效果,首先我们需要一个表来保存用户输入的关键字,通过累积,当用户输入“abb”时,若数据库已经储存了这类关键字,就找出前十条记录,然后到索引里查找结果,匹配的记录总数,然后返回。当然这要利用ajax技术咯!我们还做了缓存的处理,对于用户输入过的关键字不进行重复搜索,这减少了通信的次数,自然是提高了性能。 你这个搜索结果是查询次数还是搜索的数据总数?感觉你是搜索次数,还有就是当数据达到一定数量的时候还准确吗,特别是不用数据库的时候,例如HADOOP,HBASE时还能统计吗? |
|
lym6520
2009-07-14
zxh116116 写道 lym6520 写道 对于Lucence搜索技术,早前几个月就已经接触过了,也看了不少资料,这周才用上这个了不起的搜索技术,做出来的效果更Google差不多,不过技术肯定没人家的好,主要是数据量不大,很适用,发两张效果图看看:
![]() ![]() 其实效果是达到了,不过性能还待优化,自然速度不会比Google的差,当然最主要的原因是我们数据量小。 呵,现在谈谈创建索引、增加索引、修改索引、删除索引时要注意的一些细节吧! 创建索引的时候我们要先声明一个IndexWriter对象,这时要注意了,实例化一个IndexWriter的时候需要三个参数,第一参数是索引存放的目录,第二个参数是解析器类型,最主要的是第三个参数create是布尔型的,当创建新索引时应当是true,当我们要修改、删除、添加索引时,应当要设成false,否则当你搜索的时候会出现“nDocs must be > 0”的错误,索引在对索引进行增、删、改的时候要特别小心。 IndexWriter writer = new IndexWriter(dir, getAnalyzer(),create); 现在说说怎么实现类似Google搜索效果吧! 要实现这样的效果,首先我们需要一个表来保存用户输入的关键字,通过累积,当用户输入“abb”时,若数据库已经储存了这类关键字,就找出前十条记录,然后到索引里查找结果,匹配的记录总数,然后返回。当然这要利用ajax技术咯!我们还做了缓存的处理,对于用户输入过的关键字不进行重复搜索,这减少了通信的次数,自然是提高了性能。 你这个搜索结果是查询次数还是搜索的数据总数?感觉你是搜索次数,还有就是当数据达到一定数量的时候还准确吗,特别是不用数据库的时候,例如HADOOP,HBASE时还能统计吗? 搜索结果当然是搜索的数据总数,不管用户输入什么信息,都可以做出统计的。 |
|
huiwolf007
2009-07-20
以查找到的“abb 约1443个结果”为例,这个1443是按照关键字abb匹配到得记录总数,是么?
|
|
lym6520
2009-07-20
huiwolf007 写道 以查找到的“abb 约1443个结果”为例,这个1443是按照关键字abb匹配到得记录总数,是么?
恩,是的。 |