笔记:lucene学习

来源:互联网 发布:12306自动抢票软件 编辑:程序博客网 时间:2024/06/05 21:09

流程:

创建索引库:

1) 创建JavaBean对象

2) 创建Docment对象

3) 将JavaBean对象所有的属性值,均放到Document对象中去,属性名可以和JavaBean相同或不同

4) 创建IndexWriter对象

5) 将Document对象通过IndexWriter对象写入索引库中

6) 关闭IndexWriter对象

根据关键字查询索引库中的内容:

1) 创建IndexSearcher对象

2) 创建QueryParser对象

3) 创建Query对象来封装关键字

4) 用IndexSearcher对象去索引库中查询符合条件的前100条记录,不足100条记录的以实际为准

5) 获取符合条件的编号

6) 用indexSearcher对象去索引库中查询编号对应的Document对象

7) 将Document对象中的所有属性取出,再封装回JavaBean对象中去,并加入到集合中保存,以备将之用

实现:

步一:创建manven工程,取名叫search-lucene

步二:导入依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>cn.it.lucene</groupId><artifactId>search-lucene</artifactId><version>0.0.1-SNAPSHOT</version><packaging>war</packaging><!-- 集中定义依赖版本号 --><properties><junit.version>4.10</junit.version><spring.version>4.1.3.RELEASE</spring.version><mybatis.version>3.2.8</mybatis.version><mybatis.spring.version>1.2.2</mybatis.spring.version><mybatis.paginator.version>1.2.15</mybatis.paginator.version><mysql.version>5.1.32</mysql.version><slf4j.version>1.6.4</slf4j.version><jackson.version>2.4.2</jackson.version><druid.version>1.0.9</druid.version><httpclient.version>4.3.5</httpclient.version><jstl.version>1.2</jstl.version><servlet-api.version>2.5</servlet-api.version><jsp-api.version>2.0</jsp-api.version><commons-lang3.version>3.3.2</commons-lang3.version><commons-io.version>1.3.2</commons-io.version><lucene-version>3.0.2</lucene-version><beanutils-version>1.8.0</beanutils-version><pagehelper.version>3.7.5</pagehelper.version><mapper.version>2.3.4</mapper.version></properties><dependencies><!-- lucene依赖 --><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-core</artifactId><version>${lucene-version}</version></dependency><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-analyzers</artifactId><version>${lucene-version}</version></dependency><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-highlighter</artifactId><version>${lucene-version}</version></dependency><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-memory</artifactId><version>${lucene-version}</version></dependency><!-- IKAnalyzer3.2.0Stable网上找不到依赖,自己下载后弄的 --><dependency><groupId>IKAnalyzer</groupId><artifactId>IKAnalyzer3.2.0Stable</artifactId><version>1.1</version></dependency><!-- 单元测试 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version><scope>test</scope></dependency><!-- Spring --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>${spring.version}</version></dependency><!-- Mybatis --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>${mybatis.version}</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>${mybatis.spring.version}</version></dependency><!-- MySql --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>${slf4j.version}</version></dependency><!-- Jackson Json处理工具包 --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>${jackson.version}</version></dependency><!-- 连接池 --><dependency><groupId>com.jolbox</groupId><artifactId>bonecp-spring</artifactId><version>0.8.0.RELEASE</version></dependency><!-- JSP相关 --><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>${jstl.version}</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>${servlet-api.version}</version><scope>provided</scope></dependency><dependency><groupId>javax.servlet</groupId><artifactId>jsp-api</artifactId><version>${jsp-api.version}</version><scope>provided</scope></dependency><!-- Apache工具组件 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>${commons-lang3.version}</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-io</artifactId><version>${commons-io.version}</version></dependency><!-- beanutils --><dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils-core</artifactId><version>${beanutils-version}</version></dependency><!-- 分页助手 --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>${pagehelper.version}</version></dependency><dependency><groupId>com.github.jsqlparser</groupId><artifactId>jsqlparser</artifactId><version>0.9.1</version></dependency><!-- 通用Mapper的依赖 --><dependency><groupId>com.github.abel533</groupId><artifactId>mapper</artifactId><version>${mapper.version}</version></dependency></dependencies></project>

步三:web.xml

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"id="MyWebApp" version="2.5"><display-name>lucene-search</display-name><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/applicationContext*.xml</param-value></context-param><!--Spring的ApplicationContext 载入 --><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- 添加编码过滤器,指定编码为UTF-8,解决POST请求的中文乱码 --><filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param></filter><filter-mapping><filter-name>CharacterEncodingFilter</filter-name><url-pattern>/service/*</url-pattern></filter-mapping><!-- SpringMVC的入口 --><servlet><servlet-name>lucene-search</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/lucene-search-servlet.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>lucene-search</servlet-name><url-pattern>*.html</url-pattern></servlet-mapping><servlet-mapping><servlet-name>lucene-search</servlet-name><url-pattern>/service/*</url-pattern></servlet-mapping><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list></web-app>

步四:配置文件


mybatis-config.xml:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE configuration    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"    "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><settings><!-- 开启字段名和属性名驼峰似的匹配 --><setting name="mapUnderscoreToCamelCase" value="true" /><!-- 开启延迟加载 --><!-- <setting name="lazyLoadingEnabled" value="true"/> --><!-- 按需延迟加载 --><!-- <setting name="aggressiveLazyLoading" value="false"/> --></settings><!-- 分页插件 --><plugins>    <plugin interceptor="com.github.pagehelper.PageHelper">        <property name="dialect" value="mysql"/>        <!-- 设置为true时,使用RowBounds分页会进行count查询 -->        <property name="rowBoundsWithCount" value="true"/>    </plugin>        <plugin interceptor="com.github.abel533.mapperhelper.MapperInterceptor"><!-- 主键生成方式 --><property name="IDENTITY" value="MYSQL" /><!-- 指定了Mapper接口 --><property name="mappers" value="com.github.abel533.mapper.Mapper" /></plugin></plugins></configuration>

applicationContext.xml:

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"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-4.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"><!-- 使用spring自带的占位符替换功能 --><beanclass="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><!-- 允许JVM参数覆盖 --><property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /><!-- 忽略没有找到的资源文件 --><property name="ignoreResourceNotFound" value="true" /><!-- 配置资源文件 --><property name="locations"><list><value>classpath:jdbc.properties</value><value>classpath:env.properties</value></list></property></bean><!-- 扫描包 --><context:component-scan base-package="cn.it" /><!-- 定义数据源 --><bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource"destroy-method="close"><!-- 数据库驱动 --><property name="driverClass" value="${jdbc.driver}" /><!-- 相应驱动的jdbcUrl --><property name="jdbcUrl" value="${jdbc.url}" /><!-- 数据库的用户名 --><property name="username" value="${jdbc.username}" /><!-- 数据库的密码 --><property name="password" value="${jdbc.password}" /><!-- 检查数据库连接池中空闲连接的间隔时间,单位是分,默认值:240,如果要取消则设置为0 --><property name="idleConnectionTestPeriod" value="60" /><!-- 连接池中未使用的链接最大存活时间,单位是分,默认值:60,如果要永远存活设置为0 --><property name="idleMaxAge" value="30" /><!-- 每个分区最大的连接数 判断依据:请求并发数 --><property name="maxConnectionsPerPartition" value="100" /><!-- 每个分区最小的连接数 --><property name="minConnectionsPerPartition" value="5" /></bean><!-- 定义Mybatis的SessionFactory --><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="configLocation" value="classpath:mybatis/mybatis-config.xml" /><!-- <property name="mapperLocations" value="classpath:mybatis/mappers/**/*.xml" /> --></bean><!-- 扫描指定包下面的Mapper,并且自动注入到bean中 --><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="cn.it.lucene.mapper" /></bean><!-- 定义事务管理器 --><bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><!-- 定义事务策略 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><!--所有以query开头的方法都是只读的 --><tx:method name="query*" read-only="true" /><!--其他方法使用默认事务策略 --><tx:method name="*" /></tx:attributes></tx:advice><aop:config><!--pointcut元素定义一个切入点,execution中的第一个星号 用以匹配方法的返回类型, 这里星号表明匹配所有返回类型。 com.abc.dao.*.*(..)表明匹配cn.itcast.mybatis.dao包下的所有类的所有 方法 --><aop:pointcut id="myPointcut"expression="execution(* cn.it.lucene.service.*.*(..))" /><!--将定义好的事务处理策略应用到上述的切入点 --><aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut" /></aop:config></beans>
lucene-search-servlet.xml:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 注解驱动 --><mvc:annotation-driven /><context:component-scan base-package="cn.it.lucene.controller" /><!-- Example: prefix="/WEB-INF/jsp/", suffix=".jsp", viewname="test" -> "/WEB-INF/jsp/test.jsp" --><beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/views/" /><property name="suffix" value=".jsp" /></bean></beans>
jdbc.properties:

jdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://127.0.0.1:3306/taotao?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=truejdbc.username=rootjdbc.password=root
env.properties:里面没东西
步五:用于测试的表,数据库名为taotao,下面为sql创建表

CREATE TABLE `tb_item` (  `id` bigint(20) NOT NULL auto_increment COMMENT '商品id,同时也是商品编号',  `title` varchar(100) NOT NULL COMMENT '商品标题',  `sell_point` varchar(500) default NULL COMMENT '商品卖点',  `price` bigint(20) NOT NULL COMMENT '商品价格,单位为:分',  `num` int(10) NOT NULL COMMENT '库存数量',  `barcode` varchar(30) default NULL COMMENT '商品条形码',  `image` varchar(500) default NULL COMMENT '商品图片',  `cid` bigint(10) NOT NULL COMMENT '所属类目,叶子类目',  `status` tinyint(4) NOT NULL default '1' COMMENT '商品状态,1-正常,2-下架,3-删除',  `created` datetime NOT NULL COMMENT '创建时间',  `updated` datetime NOT NULL COMMENT '更新时间',  PRIMARY KEY  (`id`),  KEY `cid` (`cid`),  KEY `status` (`status`),  KEY `updated` (`updated`)) ENGINE=InnoDB AUTO_INCREMENT=1474391931 DEFAULT CHARSET=utf8 COMMENT='商品表'
步六:java类


BasePojo:

package cn.it.lucene.pojo;import java.util.Date;public abstract class BasePojo {        private Date created;    private Date updated;    public Date getCreated() {        return created;    }    public void setCreated(Date created) {        this.created = created;    }    public Date getUpdated() {        return updated;    }    public void setUpdated(Date updated) {        this.updated = updated;    }}
Item:

package cn.it.lucene.pojo;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.Table;import org.apache.commons.lang3.StringUtils;/** * 商品 * */@Table(name = "tb_item")public class Item extends BasePojo {    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    private Long id;// 商品id,同时也是商品编号    private String title;// 商品标题    private String sellPoint;// 商品卖点    private Long price;// 商品价格,单位为:分    private String image;// 商品图片    private Long cid;// 所属类目,叶子类目    private Integer status;// 商品状态,1-正常,2-下架,3-删除    private Integer num;// 库存数量    private String barcode;// 商品条形码    public Long getId() {        return id;    }    public void setId(Long id) {        this.id = id;    }    public String getTitle() {        return title;    }    public void setTitle(String title) {        this.title = title;    }    public String getSellPoint() {        return sellPoint;    }    public void setSellPoint(String sellPoint) {        this.sellPoint = sellPoint;    }    public Integer getNum() {        return num;    }    public void setNum(Integer num) {        this.num = num;    }    public String getBarcode() {        return barcode;    }    public void setBarcode(String barcode) {        this.barcode = barcode;    }    public Long getPrice() {        return price;    }    public void setPrice(Long price) {        this.price = price;    }    public String getImage() {        return image;    }    public void setImage(String image) {        this.image = image;    }    public Long getCid() {        return cid;    }    public void setCid(Long cid) {        this.cid = cid;    }    public Integer getStatus() {        return status;    }    public void setStatus(Integer status) {        this.status = status;    }    public String[] getImages() {        return this.getImage() == null ? null : StringUtils.split(this.getImage(), ',');    }    @Override    public String toString() {        return "Item [id=" + id + ", title=" + title + ", sellPoint=" + sellPoint + ", price=" + price                + ", image=" + image + ", cid=" + cid + ", status=" + status + "]";    }}

ItemMapper:

package cn.it.lucene.mapper;import cn.it.lucene.pojo.Item;import com.github.abel533.mapper.Mapper;public interface ItemMapper extends Mapper<Item>{}
LuceneUtil:

package cn.it.lucene.util;import java.io.File;import java.lang.reflect.Method;import org.apache.commons.beanutils.BeanUtils;import org.apache.commons.lang3.StringUtils;import org.apache.lucene.analysis.Analyzer;import org.apache.lucene.analysis.cjk.CJKAnalyzer;import org.apache.lucene.document.Document;import org.apache.lucene.document.Field;import org.apache.lucene.document.Field.Index;import org.apache.lucene.document.Field.Store;import org.apache.lucene.index.IndexWriter.MaxFieldLength;import org.apache.lucene.store.Directory;import org.apache.lucene.store.FSDirectory;import org.apache.lucene.util.Version;import org.wltea.analyzer.lucene.IKAnalyzer;/** * 工具类 *  * @author yeheng */public class LuceneUtil {    public static final String DIRECTORYS = "E:/IndexDB";    private static Directory directory; // 目录    private static Version version; // 版本    private static Analyzer analyzer; // 分词    private static MaxFieldLength maxFieldLength; // 最大文件长度    static {        try {            directory = FSDirectory.open(new File(DIRECTORYS));            version = Version.LUCENE_30;            analyzer = new IKAnalyzer(); // 使用第三方分词器IKAnalyzer//            analyzer = new CJKAnalyzer(version);            maxFieldLength = MaxFieldLength.LIMITED;        } catch (Exception e) {            e.printStackTrace();            throw new RuntimeException(e);        }    }    public static Directory getDirectory() {        return directory;    }    public static Version getVersion() {        return version;    }    public static Analyzer getAnalyzer() {        return analyzer;    }    public static MaxFieldLength getMaxFieldLength() {        return maxFieldLength;    }    private LuceneUtil() {    }    /**     * 将JavaBean转成Document对象     *      * @param obj 实体对象JavaBean     * @return Document对象     * @throws Exception     */    @SuppressWarnings({ "rawtypes", "unchecked" })    public static Document javabean2document(Object obj) throws Exception {        // 创建Docuemnt对象        Document document = new Document();        // 获取obj引用的对象字节码        Class clazz = obj.getClass();        // 通过对象字节码获取私有的属性        java.lang.reflect.Field[] reflectFields = clazz.getDeclaredFields();        // 迭代        for (java.lang.reflect.Field reflectField : reflectFields) {            // 强力反射            reflectField.setAccessible(true);            // 获取属性名            String name = reflectField.getName();            // 人工拼接方法名            String methodName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);            // 获取方法,例如:getId()/getTitle()/getContent()            Method method = clazz.getMethod(methodName, null);            String value=null;            if (!org.springframework.util.StringUtils.isEmpty(method.invoke(obj, null))) {                // 执行方法                value = method.invoke(obj, null).toString();            }else{//                value="1";                continue;            }            // 加入到Document对象中去,这时javabean的属性与document对象的属性相同            document.add(new Field(name, value, Store.YES, Index.ANALYZED));        }        // 返回document对象        return document;    }    /**     * 将Document对象转成JavaBean对象     *      * @param document Document对象     * @param clazz 对象字节码     * @return 实体对象JavaBean     * @throws Exception     */    @SuppressWarnings("rawtypes")    public static Object document2javabean(Document document, Class clazz) throws Exception {        Object obj = clazz.newInstance();        // 通过对象字节码获取私有的属性        java.lang.reflect.Field[] reflectFields = clazz.getDeclaredFields();        for (java.lang.reflect.Field reflectField : reflectFields) {            // 强力反射            reflectField.setAccessible(true);            // 获取属性名 例如 id/title/content            String name = reflectField.getName();            // 获取对应的值            String value = document.get(name);            // 封装javabean对应的属性中去,通过setXxx()方法            BeanUtils.setProperty(obj, name, value);        }        return obj;    }}

PageInfo:

package cn.it.lucene.bean;import java.util.List;public class PageInfo<T> {    private Long total;    private List<T> rows;    public PageInfo() {    }        public PageInfo(Long total, List<T> rows) {        this.total = total;        this.rows = rows;    }    public Long getTotal() {        return total;    }    public void setTotal(Long total) {        this.total = total;    }    public List<T> getRows() {        return rows;    }    public void setRows(List<T> rows) {        this.rows = rows;    }}

BaseService:

package cn.it.lucene.service;import java.util.Date;import java.util.List;import org.springframework.beans.factory.annotation.Autowired;import cn.it.lucene.pojo.BasePojo;import com.github.abel533.entity.Example;import com.github.abel533.mapper.Mapper;import com.github.pagehelper.PageHelper;import com.github.pagehelper.PageInfo;public abstract class BaseService<T extends BasePojo> {    /** 由子类实现该方法,返回具体的Mapper的实现类 **///    public abstract Mapper<T> getMapper();        @Autowired    private Mapper<T> mapper;        public Mapper<T> getMapper() {        return mapper;    }    /**     * 根据主键id查询数据     *      * @param id     * @return     */    public T queryById(Long id) {        return this.mapper.selectByPrimaryKey(id);    }    /**     * 查询所有数据     *      * @return     */    public List<T> queryAll() {        return this.mapper.select(null);    }    /**     * 根据条件查询数据集合     *      * @param t     * @return     */    public List<T> queryByWhere(T t) {        return this.mapper.select(t);    }    /**     * 根据条件查询一条数据     *      * @param t     * @return     */    public T queryOne(T t) {        return this.mapper.selectOne(t);    }    /**     * 分页查询数据     *      * @param t     * @param page     * @param rows     * @return     */    public PageInfo<T> queryPageListByWhere(T t, Integer page, Integer rows) {        PageHelper.startPage(page, rows, true);// 设置分页参数        // 查询数据        List<T> list = this.queryByWhere(t);        return new PageInfo<T>(list);    }        /**     * 自定义查询条件,分页查询     *      * @param example     * @param page     * @param rows     * @return     */    public PageInfo<T> queryPageListByExample(Example example, Integer page, Integer rows) {        PageHelper.startPage(page, rows, true);// 设置分页参数        // 查询数据        List<T> list = this.mapper.selectByExample(example);        return new PageInfo<T>(list);    }    /**     * 新增数据     *      * @param t     * @return     */    public Integer save(T t) {        t.setCreated(new Date());        t.setUpdated(t.getCreated());        return this.mapper.insert(t);    }    /**     * 新增数据,使用不为null的字段     *      * @param t     * @return     */    public Integer saveSelective(T t) {        t.setCreated(new Date());        t.setUpdated(t.getCreated());        return this.mapper.insertSelective(t);    }    /**     * 更新数据     *      * @param t     * @return     */    public Integer update(T t) {        t.setUpdated(new Date());        return this.mapper.updateByPrimaryKey(t);    }    /**     * 更新数据,使用不为null的字段     *      * @param t     * @return     */    public Integer updateSelective(T t) {        t.setUpdated(new Date());        return this.mapper.updateByPrimaryKeySelective(t);    }    /**     * 更加主键id删除数据     *      * @param id     * @return     */    public Integer deleteById(Long id) {        return this.mapper.deleteByPrimaryKey(id);    }    /**     * 批量删除     *      * @param ids     * @param property     * @param clazz     * @return     */    public Integer deleteByIds(List<Object> ids, String property, Class<T> clazz) {        Example example = new Example(clazz);        example.createCriteria().andIn(property, ids);        return this.mapper.deleteByExample(example);    }}

ItemService:(核心代码)

package cn.it.lucene.service;import java.io.File;import java.util.ArrayList;import java.util.List;import org.apache.lucene.document.Document;import org.apache.lucene.index.IndexWriter;import org.apache.lucene.index.Term;import org.apache.lucene.queryParser.MultiFieldQueryParser;import org.apache.lucene.queryParser.QueryParser;import org.apache.lucene.search.IndexSearcher;import org.apache.lucene.search.Query;import org.apache.lucene.search.ScoreDoc;import org.apache.lucene.search.TopDocs;import org.apache.lucene.search.highlight.Formatter;import org.apache.lucene.search.highlight.Highlighter;import org.apache.lucene.search.highlight.QueryScorer;import org.apache.lucene.search.highlight.Scorer;import org.apache.lucene.search.highlight.SimpleHTMLFormatter;import org.apache.lucene.store.Directory;import org.apache.lucene.store.FSDirectory;import org.apache.lucene.store.RAMDirectory;import org.springframework.stereotype.Service;import cn.it.lucene.bean.PageInfo;import cn.it.lucene.pojo.Item;import cn.it.lucene.util.LuceneUtil;@Servicepublic class ItemService extends BaseService<Item> {    // 根据什么字段搜索    private static final String[] ARRAY = { "id", "title", "sellPoint", "price", "cid", "status" };    //最多显示的条数    private static final Integer COUNT=500;    /**     * 增加document对象到索引库中     *      * @throws Exception     */    public void addItemLucene() throws Exception {        // 从数据库中找出所有item        List<Item> list = super.queryAll();        // for循环导入数据到索引库        for (int i = 0; i < list.size(); i++) {            // 将JavaBean转成Document对象            Document document = LuceneUtil.javabean2document(list.get(i));            // 硬盘索引库            Directory fsDirectory = FSDirectory.open(new File(LuceneUtil.DIRECTORYS));            // 内存索引库,因为硬盘索引库的内容要同步到内存索引库中            Directory ramDirectory = new RAMDirectory(fsDirectory);            // 指向硬盘索引库的字符流,true表示如果内存索引库中和硬盘索引库中的相同的document对象时,先删除硬盘索引库中的document对象,            // 再将内存索引库的document对象写入硬盘索引库中            // 反之是false,默认为false,这个boolean值写在硬盘字符流的构造器            IndexWriter fsIndexWriter = new IndexWriter(fsDirectory, LuceneUtil.getAnalyzer(), true,                    LuceneUtil.getMaxFieldLength());            // 指向内存索引库的字符流            IndexWriter ramIndexWriter = new IndexWriter(ramDirectory, LuceneUtil.getAnalyzer(),                    LuceneUtil.getMaxFieldLength());            //人工设置该document的得分 走后门            //document.setBoost(100F);            // 将document对象写入内存索引库            ramIndexWriter.addDocument(document);          //设置合并因子,即满足100个cfs文本一合并            ramIndexWriter.setMergeFactor(100);            ramIndexWriter.close();            // 将内存索引库的所有document对象同步到硬盘索引库中            fsIndexWriter.addIndexesNoOptimize(ramDirectory);            //设置合并因子,即满足100个cfs文本一合并            fsIndexWriter.setMergeFactor(100);            //关闭流            fsIndexWriter.close();        }    }    /**     * 根据关键字,从索引库中查询记录     * @param keywords 关键字     * @param page 页数     * @param rows 一页条数     * @return PageInfo<Item>     * @throws Exception     */    @SuppressWarnings("resource")    public PageInfo<Item> findAllLucene(String keywords,Integer page, Integer rows) throws Exception {        List<Item> articleList = new ArrayList<Item>();        // //单字段搜索        // QueryParser queryParser = new QueryParser(LuceneUtil.getVersion(), "title",        // LuceneUtil.getAnalyzer());        // 多字段搜索,好处:搜索的范围大,最大限度匹配搜索结果        QueryParser queryParser = new MultiFieldQueryParser(LuceneUtil.getVersion(), ARRAY,                LuceneUtil.getAnalyzer());        Query query = queryParser.parse(keywords);        IndexSearcher indexSearcher = new IndexSearcher(LuceneUtil.getDirectory());        // 按得分度高低排序        TopDocs topDocs = indexSearcher.search(query, COUNT);        // 创建排序对象        // 参数一:id表示依据document对象中的哪个字段排序,例如:id        // 参数二:SortField.INT表示document对象中该字段的类型,以常量方式书写        // 参数三:true表示降序,类似于order by id desc        // 参数三:false表示升序,类似于order by id asc        // Sort sort = new Sort(new SortField("id",SortField.INT,false));        // 按count字段的降序排列,如果count字段相同的话,再按id的升序排序        // Sort sort = new Sort(new SortField("count", SortField.INT, true), new SortField("id",        // SortField.INT,        // false));        // sort表示排序的条件        // TopDocs topDocs = indexSearcher.search(query, null, 100, sort);        // 格式对象        Formatter formatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");        // 关键字对象        Scorer scorer = new QueryScorer(query);        // 高亮对象        Highlighter highlighter = new Highlighter(formatter, scorer);        for (int i = 0; i < topDocs.scoreDocs.length; i++) {            ScoreDoc scoreDoc = topDocs.scoreDocs[i];            int no = scoreDoc.doc;          //获取document对象的评分//            float score = scoreDoc.score;//            System.out.println("score=" + score);            // 关键字没有高亮            Document document = indexSearcher.doc(no);                        //for循环让关键字高亮            for (int j = 0; j < ARRAY.length; j++) {                String highlighterField=null;                if(document.get(ARRAY[j])!=null){                    // 关键字高亮                    highlighterField = highlighter.getBestFragment(LuceneUtil.getAnalyzer(), ARRAY[j],                            document.get(ARRAY[j]));                }                 if(highlighterField!=null){                     // 将高亮后的结果再次封装到document对象中                     document.getField(ARRAY[j]).setValue(highlighterField);                 }            }            Item item = (Item) LuceneUtil.document2javabean(document, Item.class);            articleList.add(item);        }//        PageHelper.startPage(page, rows, true);// 设置分页参数        return new PageInfo<Item>(Long.valueOf(COUNT),articleList);//        return articleList;    }    /**     * 删除所有索引库的内容     * @throws Exception     */    public void deleteAllLucene() throws Exception{            IndexWriter indexWriter = new IndexWriter(LuceneUtil.getDirectory(),LuceneUtil.getAnalyzer(),LuceneUtil.getMaxFieldLength());            indexWriter.deleteAll();            indexWriter.close();    }    /**     * 根据id删除索引库的内容     * @param id     * @throws Exception     */    public void deleteLucene(Long id) throws Exception{        Term term = new Term("id",String.valueOf(id));        IndexWriter indexWriter = new IndexWriter(LuceneUtil.getDirectory(),LuceneUtil.getAnalyzer(),LuceneUtil.getMaxFieldLength());        indexWriter.deleteDocuments(term);        indexWriter.close();    }    /**     * 根据id更新索引库的内容     * @param id     * @throws Exception     */    public void updateLucene(Long id) throws Exception{        Item item=super.queryById(id);        Document document = LuceneUtil.javabean2document(item);        Term term = new Term("id",String.valueOf(id));        IndexWriter indexWriter = new IndexWriter(LuceneUtil.getDirectory(),LuceneUtil.getAnalyzer(),LuceneUtil.getMaxFieldLength());        indexWriter.updateDocument(term,document);        indexWriter.close();    }}
ItemSearchController:

package cn.it.lucene.controller;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.servlet.ModelAndView;import cn.it.lucene.bean.PageInfo;import cn.it.lucene.pojo.Item;import cn.it.lucene.service.ItemService;/** * 商品搜索 */@Controllerpublic class ItemSearchController {    private static final Logger LOGGER = LoggerFactory.getLogger(ItemSearchController.class);    @Autowired    private ItemService itemService;    /**     * 根据关键字查询数据,跳转到search视图     * @param keyword     * @param page     * @param rows     * @return     */    @RequestMapping(value = "search", method = RequestMethod.GET)    public ModelAndView search(@RequestParam("keyword") String keyword,            @RequestParam(value = "page", defaultValue = "1") Integer page,            @RequestParam(value = "rows", defaultValue = "28") Integer rows) {        ModelAndView mv = new ModelAndView("search");        mv.addObject("query", keyword);        mv.addObject("page", page);        try {            PageInfo<Item> pageInfo=this.itemService.findAllLucene(keyword, page, rows);            mv.addObject("itemList", pageInfo.getRows());            mv.addObject("pages", (pageInfo.getTotal() + rows - 1) / rows);        } catch (Exception e) {            LOGGER.error("根据关键字从索引库中获取数据失败,关键字:"+keyword,e);        }        return mv;    }}
步7:测试导入数据

ItemServiceTest:

package cn.it.lucene.service.test;import java.util.List;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import cn.it.lucene.bean.PageInfo;import cn.it.lucene.pojo.Item;import cn.it.lucene.service.ItemService;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = {"classpath:spring/applicationContext*.xml"})public class ItemServiceTest {    @Autowired    private ItemService itemService;    /**     * 测试导入数据     * @throws Exception     */    @Test    public void add() throws Exception {        this.itemService.addItemLucene();    }    @Test    public void query() throws Exception {        PageInfo<Item> page=this.itemService.findAllLucene("小米",1,10);        List<Item> list=page.getRows();        for(Item item:list){                        System.out.println(item);        }    }}
步八:视图

视图这里省略


步九:启动tomcat访问路径http://127.0.0.1:8080/search-lucene/search.html?keyword=小米,效果如下:




0 0
原创粉丝点击