Lucene使用笔记

package name.ixr.service;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;

import name.ixr.collector.GroupingCollector;
import name.ixr.dao.SearchDao;
import name.ixr.util.SqlUtil;
import name.ixr.vo.SearchResultSet;

import org.apache.lucene.analysis.Analyzer;
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.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.util.Version;
import org.wltea.analyzer.lucene.IKAnalyzer;

/**
 * 搜索引擎逻辑
 * 
 * @author IXR
 */
public class SearchService {

    private static final String CONF_PATH = "jdbc.properties"; // 数据库配置文件
    /** 时间格式化(lucene只认识这个格式yyyyMMddHHmmss) */
    public static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
    /** 数据库查询工具包 */
    private static SqlUtil sqlUtil = null;
    /** 索引位置 */
    private static File INDEX_DIR = null;
    
    static {
        Properties properties = new Properties();
        InputStream inputStream = Object.class.getResourceAsStream("/" + CONF_PATH);
        try {
            properties.load(inputStream);
            inputStream.close();
        } catch (IOException e) {
            System.err.println("数据库配置文件加载失败");
        }
        try {
            sqlUtil = new SqlUtil(properties);
        } catch (ClassNotFoundException e) {
            System.err.println("找不到数据库连接驱动");
        }
        String path = properties.getProperty("index");
        URI dirUri = null;
        try {
            String starts = "classpath:";
            if (path.startsWith(starts)) {
                path = path.substring(starts.length());
                dirUri = Class.class.getResource("/").toURI();
                dirUri = new URI(dirUri.toString() + path);
            } else {
                dirUri = new URI(path);
            }
        } catch (URISyntaxException e) {
            System.err.println("索引目录构建失败");
        }
        INDEX_DIR = new File(dirUri);
    }
    
    /**
     * 删除索引
     */
    private static void dropIndex() {
        for (File file : INDEX_DIR.listFiles()) {
            file.delete();
        }
    }

    /**
     * 获取索引目录
     * 
     * @return
     * @throws IOException
     */
    private static Directory getDirectory() throws IOException {
        return FSDirectory.open(INDEX_DIR);
    }

    /**
     * 获取分词器
     * 
     * @return
     */
    private static Analyzer getAnalyzer() {
        // StandardAnalyzer,IKAnalyzer
        Analyzer analyzer = new IKAnalyzer();
        return analyzer;
    }

    /**
     * 添加索引
     * 
     * @param documents
     *            要添加的索引文档
     * 
     * @throws CorruptIndexException
     * @throws LockObtainFailedException
     * @throws IOException
     */
    private static void addDocument(Document... documents) throws CorruptIndexException, LockObtainFailedException, IOException {
        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_32, getAnalyzer());
        IndexWriter writer = new IndexWriter(getDirectory(), indexWriterConfig);
        for (Document document : documents) {
            writer.addDocument(document);
        }
        writer.optimize();
        writer.close();
    }

    /**
     * 更新搜索引擎索引
     * 
     * @throws SQLException
     * @throws IOException
     * @throws LockObtainFailedException
     * @throws CorruptIndexException
     * @return
     */
    public static long updateIndex() throws SQLException, CorruptIndexException, LockObtainFailedException, IOException {
        Date beginDate = new Date();
        Connection connection = sqlUtil.getConnection();
        Statement teamStatement = connection.createStatement();
        ResultSet teams = SearchDao.searchTeam(teamStatement);
        ResultSetMetaData metaData = teams.getMetaData();
        Map<String, String> fieldTypeMap = new HashMap<String, String>();
        for (int i = 0; i < metaData.getColumnCount(); i++) {
            fieldTypeMap.put(metaData.getColumnName(i + 1), metaData.getColumnTypeName(i + 1));
        }
        List<Document> documents = new ArrayList<Document>();
        while (teams.next()) {
            Document document = new Document();
            for (String field : fieldTypeMap.keySet()) {
                String typeName = fieldTypeMap.get(field);
                String value = teams.getString(field);
                if ("datetime".equals(typeName)) {
                    value = dateFormat.format(teams.getDate(field));
                } else {
                    value = teams.getString(field);
                }
                if (value != null) {
                    Field dField = null;
                    if ("uniqueidentifier".equals(typeName) || "int".equals(typeName) || "decimal".equals(typeName) || "datetime".equals(typeName)) {
                        dField = new Field(field, value, Store.YES, Index.NOT_ANALYZED_NO_NORMS);
                    } else {
                        dField = new Field(field, value, Store.YES, Index.ANALYZED);
                    }
                    document.add(dField);
                }
            }
            documents.add(document);
        }
        addDocument(documents.toArray(new Document[0]));
        teams.close();
        teamStatement.close();
        connection.close();
        Date endDate = new Date();
        return endDate.getTime() - beginDate.getTime();
    }

    /**
     * 按字段搜索
     * 
     * @param fields
     *            要搜索的字段集合
     * @param keyword
     *            要搜索的关键词
     * @param sortField
     *            排序字段
     * @param desc
     *            排序正负
     * @param group
     *            分组字段,如果为空不分组
     * @param page
     *            页码
     * @param size
     *            数量
     * @throws CorruptIndexException
     * @throws IOException
     * @throws ParseException
     */
    private static SearchResultSet search(String[] fields, String keyword, String sortField, boolean desc, String groupField, int page, int size) throws CorruptIndexException, IOException,
            ParseException {
        Date beginDate = new Date();
        SearchResultSet result = new SearchResultSet();
        result.setCurrentPage(page);
        result.setPageSize(size);
        List<Document> documents = new ArrayList<Document>();
        IndexSearcher searcher = new IndexSearcher(getDirectory());
        int start = (page - 1) * size;
        int end = page * size;
        MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_32, fields, getAnalyzer());
        Query query = parser.parse(keyword);
        int total = 0;
        if (groupField != null) {
            GroupingCollector groupingCollector = new GroupingCollector(sortField, desc, groupField);
            searcher.search(query, groupingCollector);
            List<Document> s_documents = groupingCollector.getDocuments();
            total = s_documents.size();
            for (int i = start; i < end && i < total; i++) {
                documents.add(s_documents.get(i));
            }
        } else {
            TopDocs topFieldDocs = null;
            if (sortField != null) {
                topFieldDocs = searcher.search(query, end, new Sort(new SortField(sortField, Locale.CANADA, desc)));
            } else {
                topFieldDocs = searcher.search(query, end);
            }
            total = topFieldDocs.totalHits;
            for (int i = start; i < end && i < total; i++) {
                documents.add(searcher.doc(topFieldDocs.scoreDocs[i].doc));
            }
        }
        result.setTotalRows(total);
        if (total > 0) {
            int totalPages = total / size + (total % size > 0 ? 1 : 0);
            result.setTotalPages(totalPages);
        }
        result.setList(documents);
        Date endDate = new Date();
        result.setHours(endDate.getTime() - beginDate.getTime());
        return result;
    }

    public static void main(String[] args) throws Exception {
        testUpdateIndex();
        /*
         * testSeachIndex(1); testSeachIndex(2); testSeachIndex(3);
         * testSeachIndex(4);
         */
    }

    public static void testSeachIndex(int page) throws Exception {
        SearchResultSet resultSet = search(new String[] { "clinename" }, "漓江 AND \"六日\"", "dbgndate", true, null, page, 30);
        List<Document> list = resultSet.getList();
        System.out.println(String.format("About %s results (%s ms) ", resultSet.getTotalRows(), resultSet.getHours()));
        for (Document document : list) {
            System.out.println(document.get("dbgndate") + "\t" + document.get("clinename") + "\t" + document.get("ulineid"));
        }
    }

    public static void testUpdateIndex() throws Exception {
        dropIndex();
        System.out.println("平均耗时:" + updateIndex() + "ms");
    }
}


 

 

我的SQL也很强大

package name.ixr.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * 搜索提供的数据
 * 
 * @author IXR
 */
public class SearchDao {
    /**
     * 查询团队
     * 
     * @param statement
     * @return
     * @throws SQLException
     */
    public static ResultSet searchTeam(Statement statement) throws SQLException {
        StringBuffer sql = new StringBuffer();
        sql.append("select team.uid uid,team.clinename clinename,team.ulineid ulineid ");// t_team
        sql.append(",team.cteamcode cteamcode,team.idays idays,team.coptype coptype");// t_team
        sql.append(",team.iplanqty-team.ikeepqty-team.iqty remainingseats,team.cnation cnation,team.cstartcity cstartcity ");// t_team
        sql.append(",team.dbgndate dbgndate,team.denddate denddate,team.cfeature cfeature ");// t_team
        sql.append(",lineprice.nprice nprice,lineprice.nprice1 nprice1 ");// t_line_pricegg
        sql.append(",dept.ucorpid ucorpid ");// t_dept
        sql.append(",picture.cpicpath cpicpath ");// t_picture
        sql.append(",theme.[values] themes ");//t_theme
        sql.append(",tag.[values] tags ");//t_tag
        sql.append(",knowledge.knowledges knowledges ");//t_knowledge
        sql.append("from t_team team ");
        sql.append("left join (select picture.ulinkid,max(picture.cpicpath) cpicpath from t_picture picture ");
        sql.append("where picture.ctype='线路' and picture.cdisplaytype='查询' group by picture.ulinkid) ");
        sql.append("picture on picture.ulinkid=team.ulineid ");
        sql.append("left join t_line_price lineprice on lineprice.ulineid=team.ulineid and lineprice.ino=1 ");
        sql.append("left join t_dept dept on dept.uid=team.udeptid ");
        // themes
        sql.append("left join (select * from (select distinct ulinkid ");
        sql.append("from t_theme_link)a outer apply(select [values]=");
        sql.append("stuff(replace(replace((select t.cname cname from ");
        sql.append("t_theme_link u left join t_theme t on u.uthemeid = ");
        sql.append("t.uid where u.ulinkid = a.ulinkid for xml auto ), ");
        sql.append("'<t cname=\"', ','), '\"/>', '), 1, 1, '))n) ");
        sql.append("theme on theme.ulinkid=team.ulineid ");
        // tags
        sql.append("left join (select * from (select distinct uinfoid ");
        sql.append("from t_tag_link)a outer apply(select [values]=");
        sql.append("stuff(replace(replace((select t.ctagname ctagname from ");
        sql.append("t_tag_link l left join t_tag t on l.utagid = ");
        sql.append("t.uid where l.uinfoid = a.uinfoid for xml auto ), ");
        sql.append("'<t ctagname=\"', ','), '\"/>', '), 1, 1, '))n) ");
        sql.append("tag on tag.uinfoid=team.uid ");
        //knowledge
        sql.append("left join (");
        sql.append("select * from (select distinct ulinkid ");
        sql.append("from t_knowledge_link)a outer apply(select [knowledges]=");
        sql.append("stuff(replace(replace(replace(replace((select k.uid uid,k.ctitle ctitle,k.cpicpath cpicpath  from ");
        sql.append("t_knowledge_link l left join t_knowledge k on l.uknowledgeid = ");
        sql.append("k.uid left join t_team_route route on route.uid=l.ulinkid ");
        sql.append("where l.ulinkid = a.ulinkid and l.ctype='3' or route.uteamid=a.ulinkid and l.ctype='4' for xml auto ), ");
        sql.append("'<k uid=', ',{uid:'), '\"/>', '}'),'ctitle=',',ctitle:'),'cpicpath=',',cpicpath:'), 1, 1, ')");
        sql.append(")n) ");
        sql.append("knowledge on knowledge.ulinkid=team.uid order by dbgndate");
        return statement.executeQuery(sql.toString());
    }
}



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值