[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匹配到得记录总数,是么?

恩,是的。
Global site tag (gtag.js) - Google Analytics