前面两篇文章,简单尝试了lucene的一些应用,还是再回头想想我们的需求吧,我们希望能够开发一个淘宝一样的针对商品的搜索服务,提供多种条件的组合搜索,并且对于性能提出了一定的要求。同时我们希望这个小型的搜索引擎具有一定的通用性,也就是在可以预见的将来,我们可能用它进行店铺等信息的搜索,所以在我们的搜索代码中,不能织入特定的业务逻辑代码,而应该进行一定的抽象,抽离出一个通用的模型。
我们的需求很简单:
1、单值搜索
2、单值分页搜索
3、组合条件搜索
4、组合条件分页搜索
5、系统对于性能有一定要求,诸如首页的信息不能有太久的加载时间
6、搜索引擎索引的更新需要有一定的精确性,由于数据量的问题不能通过删除全部再新建的方式来完成
7、自动定时刷新功能
索引的精确刷新和自动刷新在之前的文章中已经讲解,这里不再赘述,可以直接看最下面的代码。
关于首页等这些页面渲染加载便进行搜索的情况,我们采用缓存来缓和一下搜索频率,我们在缓存中缓存3页单值搜索,比如首页加载的时候并未输入搜索条件,我们会默认的针对自己的营销数据分析来设置默认的搜索值,执行搜索。然后缓存3页有效期5分钟。对于组合查询,由于组合条件千变万化,无法通过有效的缓存来减少搜索次数,而且搜索频率将远远低于默认的单值搜索,所以不再使用缓存。
首先说单值搜索和组合搜索的问题,单值搜索和组合条件搜索其实都可以通过BooleanQuery来满足,只是单值搜索的条件下只有一个BooleanQuery条件而已,但是这里我们更愿意使用QueryParse进行分词,然后自动去搜索每一个索引,最后组装结果,而不是在外部的调用代码中通过多次的set操作来手动的对应索引的名称组装查询Map。这种情况比较适用于类似于淘宝首页最大的那个搜索框的情况,输入一个字符串可以匹配多个字段是否符合,比如标题,摘要信息,品牌信息等。
对于单值的分页查询,查询了官方的相关资料,发现没有一个类似于数据库limit操作的直接分页操作,而是需要手动进行分页,通过对查询结果的截取来获取需要的区间。我们使用之前开发的分页器来作为返回值:
对于组合查询,我们采用BooleanQuery来组装查询query,这里要注意的问题是,对于组合查询查询条件可以分成两部分:
确定的查询条件 和 不确定的查询条件。
所谓的确定查询条件,即类似于页面查询表单中勾选的商品类型,商品品牌等信息,这类信息是与固定的字段进行匹配的,这类的查询条件与其他的条件之间是AND关系。
所谓的不确定查询条件与上述的单值搜索类似,即输入的字符串与多个字段进行匹配,多个字段之间是OR的关系。
为了满足这个需求,我们设计如下的方法,来使用不同的map保存不同关系的查询,有三种即 OR关系 AND关系 BETWEEN关系,具体的请看方法签名
同样的,对于分页,我们采用相同的逻辑:
再贴一遍分页器的代码:
在前面的文章中,我们已经实现了一种精确刷新搜索引擎索引的方法,这里不再赘述,直接看代码:
缓存的代码
DAO相关的文件请参加前面的文章,或者联系邮箱发送,我们使用的是hi自己封装jdbcTemplate的DAO操作层,代码较多,这里不再贴出。