lucene searchafter分页
博客专区 > _sheldon 的博客 > 博客详情
lucene searchafter分页
_sheldon 发表于3年前
lucene searchafter分页
  • 发表于 3年前
  • 阅读 228
  • 收藏 2
  • 点赞 0
  • 评论 1

腾讯云 新注册用户 域名抢购1元起>>>   

摘要: lucene searchafter 分页
package com.gaibuy.foundation.lucene;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.DoubleField;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.IntField;
import org.apache.lucene.document.LongField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleFragmenter;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
import org.wltea.analyzer.lucene.IKAnalyzer;

/**
 * 商品lucene工具类
 * 
 */
public class GoodsLuceneUtil {
    private static File index_file = null;
    private static Analyzer analyzer;
    private static QueryParser parser;
    private static String index_path;
    private int textmaxlength = 2000;
    private static String prefixHTML = "<font color='red'>";
    private static String suffixHTML = "</font>";

    public GoodsLuceneUtil(String indexPath) {
        index_path = indexPath;
        analyzer = new IKAnalyzer(true);
        parser = new QueryParser(Version.LUCENE_4_9, GoodsLuceneVo.TITLE, analyzer);
    }

    public void setIndex_path(String path) {
        index_path = path;
    }

    /**
     * 创建索引阅读器
     * 
     * @param directoryPath
     *            索引目录
     * @return
     * @throws IOException
     *             可能会抛出IO异常
     */
    public static IndexReader createIndexReader(String index_path) throws IOException {
        return DirectoryReader.open(FSDirectory.open(new File(index_path)));
    }

    /**
     * 创建索引查询器
     * 
     * @param directoryPath
     *            索引目录
     * @return
     * @throws IOException
     */
    public static IndexSearcher createIndexSearcher(String index_path) throws IOException {
        return new IndexSearcher(createIndexReader(index_path));
    }

    /**
     * 创建索引查询器
     * 
     * @param reader
     * @return
     */
    public static IndexSearcher createIndexSearcher(IndexReader reader) {
        return new IndexSearcher(reader);
    }

    /**
     * Lucene分页查询
     * 
     * @param directoryPath
     * @param query
     * @param page
     * @throws IOException
     */
    public static void pageQuery(Query query, LuceneResult result, Sort sort) throws IOException {
        IndexSearcher searcher = createIndexSearcher(index_path);
        result.setRows(searchTotalRecord(searcher, query));
        ScoreDoc after = getLastScoreDoc(result.getCurrentPage(), result.getPageSize(), query, searcher, sort);

        TopDocs topDocs = searcher.searchAfter(after, query, result.getPageSize(), sort);
        // 设置总记录数
        List<Document> docList = new ArrayList<Document>();
        System.out.println(topDocs.totalHits + "topDocs.totalHits.......................");
        ScoreDoc[] docs = topDocs.scoreDocs;
        for (ScoreDoc scoreDoc : docs) {
            int docID = scoreDoc.doc;
            Document document = searcher.doc(docID);
            docList.add(document);
        }
        result.setDoc_list(docList);
        searcher.getIndexReader().close();
    }

    /**
     * 商品搜索
     * 
     * @param params
     * @param directoryPath
     * @param begin_price
     * @param end_price
     * @param result
     * @param sort
     * @return
     * @throws ParseException
     * @throws IOException
     */
    public LuceneResult goodsPage(String params, double begin_price, double end_price, LuceneResult result, Sort sort)
            throws ParseException, IOException {
        // 组件参数
        params = goodsBuilderParams(params, begin_price, end_price);
        try {
            parser.setAllowLeadingWildcard(true);
            Query query = parser.parse(params);
            pageQuery(query, result, sort);
            List<GoodsLuceneVo> goodsVoList = builderVoList(result.getDoc_list(), query);
            result.setGoodsVo_list(goodsVoList);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 创建索引
     * 
     * @param list
     * @throws IOException
     */
    public void writeIndex(List<GoodsLuceneVo> list) throws IOException {
        IndexWriter writer = openIndexWriter();
        try {
            for (GoodsLuceneVo lucenceVo : list) {
                Document document = builderDocument(lucenceVo);
                writer.addDocument(document);
            }
            writer.commit();
        } finally {
            writer.close();
        }
    }

    /**
     * 创建索引
     * 
     * @param vo
     */
    public void writeIndex(GoodsLuceneVo vo) {
        IndexWriter writer = null;
        try {
            writer = openIndexWriter();
            Document document = builderDocument(vo);
            writer.addDocument(document);
            // writer.optimize();
        } catch (IOException e1) {
            e1.printStackTrace();
            try {
                writer.close();
            } catch (CorruptIndexException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } finally {
            try {
                writer.close();
            } catch (CorruptIndexException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 更新索引
     * 
     * @param id
     * @param vo
     */
    public void update(String id, GoodsLuceneVo vo) {
        try {
            index_file = new File(index_path);
            Directory directory = FSDirectory.open(index_file);
            IndexWriterConfig writerConfig = new IndexWriterConfig(Version.LUCENE_4_9, analyzer);
            IndexWriter writer = new IndexWriter(directory, writerConfig);
            Document doc = builderDocument(vo);
            Term term = new Term(GoodsLuceneVo.ID, String.valueOf(id));
            writer.updateDocument(term, doc);
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除文档
     * 
     * @param id
     */
    public void delete_index(String id) {
        try {
            index_file = new File(index_path);
            Directory directory = FSDirectory.open(index_file);
            IndexWriterConfig writerConfig = new IndexWriterConfig(Version.LUCENE_4_9, analyzer);
            IndexWriter writer = new IndexWriter(directory, writerConfig);
            Term term = new Term(GoodsLuceneVo.ID, String.valueOf(id));
            writer.deleteDocuments(term);
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除所有索引
     * 
     * @param isdeletefile
     *            是否删除文件
     */
    public void deleteAllIndex(boolean isdeletefile) {
        IndexWriter indexWriter = null;
        index_file = new File(index_path);
        if ((index_file.exists()) && (index_file.isDirectory())) {
            try {
                IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_4_9, analyzer);
                indexWriter = new IndexWriter(FSDirectory.open(index_file), iwc);
                indexWriter.deleteAll();

            } catch (Exception ex) {
                ex.printStackTrace();

                if (indexWriter != null)
                    try {
                        indexWriter.close();
                    } catch (IOException localIOException) {
                    }
            } finally {
                if (indexWriter != null)
                    try {
                        indexWriter.close();
                    } catch (IOException localIOException1) {
                    }
            }
            if (isdeletefile) {

                deleteAllFile();
            }
        }
    }

    /**
     * 删除索引文件
     */
    private void deleteAllFile() {
        index_file = new File(index_path);
        File[] files = index_file.listFiles();
        for (int i = 0; i < files.length; i++)
            files[i].delete();

    }

    /**
     * 打开indexwriter
     * 
     * @return
     * @throws IOException
     */
    private IndexWriter openIndexWriter() throws IOException {
        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_4_9, analyzer);

        index_file = new File(index_path);
        indexWriterConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);
        IndexWriter writer = new IndexWriter(FSDirectory.open(index_file), indexWriterConfig);
        return writer;
    }

    /**
     * 组件document
     * 
     * @param goodsLuceneVo
     * @return
     */
    private Document builderDocument(GoodsLuceneVo goodsLuceneVo) {
        Document document = new Document();
        Field id = new LongField(GoodsLuceneVo.ID, goodsLuceneVo.getVo_id(), Store.YES);
                                                        //jsoup.clean 去掉里边的HTML代码
        Field title = new TextField(GoodsLuceneVo.TITLE, Jsoup.clean(goodsLuceneVo.getVo_title(), Whitelist.none()), Store.YES);
        Field content = new TextField(GoodsLuceneVo.CONTENT, Jsoup.clean(goodsLuceneVo.getVo_content(), Whitelist.none()),
                Store.YES);
        Field type = new StringField(GoodsLuceneVo.TYPE, goodsLuceneVo.getVo_type(), Store.YES);
        Field store_price = new DoubleField(GoodsLuceneVo.STORE_PRICE, goodsLuceneVo.getVo_store_price(), Store.YES);
        Field add_time = new LongField(GoodsLuceneVo.ADD_TIME, goodsLuceneVo.getVo_add_time(), Store.YES);
        Field goods_salenum = new IntField(GoodsLuceneVo.GOODS_SALENUM, goodsLuceneVo.getVo_goods_salenum(), Store.YES);
        document.add(id);
        document.add(title);
        document.add(content);
        document.add(type);
        document.add(store_price);
        document.add(add_time);
        document.add(goods_salenum);
        return document;
    }

    /**
     * 组件vo,包括高亮
     * 
     * @param doc
     * @param query
     * @param vo
     * @throws Exception
     */
    private void builderVo(Document doc, Query query, GoodsLuceneVo vo) throws Exception {
        SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter(prefixHTML, suffixHTML);
        Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(query));

        highlighter.setTextFragmenter(new SimpleFragmenter(this.textmaxlength));
        String content = highlighter.getBestFragment(analyzer, GoodsLuceneVo.CONTENT, doc.get(GoodsLuceneVo.CONTENT));
        String title = highlighter.getBestFragment(analyzer, GoodsLuceneVo.TITLE, doc.get(GoodsLuceneVo.TITLE));
        if (content == null)
            vo.setVo_content(doc.get(GoodsLuceneVo.CONTENT));
        else {
            vo.setVo_content(content);
        }
        if (title == null) {
            vo.setVo_title(doc.get(GoodsLuceneVo.TITLE));
        } else {
            vo.setVo_title(title);
        }
        vo.setVo_id(Long.valueOf(doc.get(GoodsLuceneVo.ID)));
        vo.setVo_url(doc.get(GoodsLuceneVo.URL));
        vo.setVo_add_time(Long.valueOf(doc.get(GoodsLuceneVo.ADD_TIME)));
        vo.setVo_store_price(Double.valueOf(doc.get(GoodsLuceneVo.STORE_PRICE)));
    }

    /**
     * 组件volist
     * 
     * @param documents
     * @param query
     * @return
     */
    private List<GoodsLuceneVo> builderVoList(List<Document> documents, Query query) {
        List<GoodsLuceneVo> goodsVoList = new ArrayList<GoodsLuceneVo>();
        try {
            for (Document document : documents) {
                GoodsLuceneVo vo = new GoodsLuceneVo();
                builderVo(document, query, vo);
                goodsVoList.add(vo);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return goodsVoList;
    }

    /**
     * 商品参数组装
     * 
     * @param params
     * @param begin_price
     * @param end_price
     * @return
     */
    private String goodsBuilderParams(String params, double begin_price, double end_price) {
        if (params.indexOf(GoodsLuceneVo.TITLE + ":") < 0) {
            params = "(" + GoodsLuceneVo.TITLE + ":" + params + " OR " + GoodsLuceneVo.CONTENT + ":" + params + ")";
        }
        if ((begin_price >= 0.0D) && (end_price > 0.0D)) {
            params = params + " AND" + GoodsLuceneVo.STORE_PRICE + ":[" + begin_price + " TO " + end_price + "]";
        }
        return params;
    }

    /**
     * @Title: searchTotalRecord
     * @Description: 获取符合条件的总记录数
     * @param query
     * @return
     * @throws IOException
     */
    public static int searchTotalRecord(IndexSearcher searcher, Query query) throws IOException {
        TopDocs topDocs = searcher.search(query, Integer.MAX_VALUE);
        if (topDocs == null || topDocs.scoreDocs == null || topDocs.scoreDocs.length == 0) {
            return 0;
        }
        // ScoreDoc[] docs = topDocs.scoreDocs;
        return topDocs.totalHits;
    }

    /**
     * 根据页码和分页大小获取上一次的最后一个ScoreDoc 获取这个scoreDoc的时候,如果有排序,一定加上排序(sort) 否则会出现ScoreDoc 无法转换FieldDoc的错误
     */
    private static ScoreDoc getLastScoreDoc(int pageIndex, int pageSize, Query query, IndexSearcher searcher, Sort sort)
            throws IOException {
        if (pageIndex == 1)
            return null;// 如果是第一页就返回空
        int num = pageSize * (pageIndex - 1);// 获取上一页的数量
        TopDocs tds = searcher.search(query, num, sort);
        return tds.scoreDocs[num - 1];
    }
}

package com.gaibuy.foundation.lucene;

public class StoreLuceneVo {
    public static final String STORE_ID = "store_id";
    public static final String STORE_ADD_TIME = "store_add_time";
    public static final String STORE_TITLE = "store_title";
    public static final String STORE_CLASS = "store_class";
    public static final String STORE_CONTENT = "store_content";
    public static final String STORE_RECOMMEND = "store_recommend";
    public static final String STORE_AREA_TYPE = "store_area_type";
    public static final String CARD_APPROVE = "card_approve";
    public static final String REALSTORE_APPROVE = "realstore_approve";
    public static final String STORE_FAVORITE_COUNT = "store_favorite_count";
    public static final String STORE_CREDIT = "store_credit";
    public static final String STORE_GRADE = "store_grade";
    public static final String STORE_POINT = "store_point";
    public static final String STORE_AREA = "store_area";

    private Long store_id;
    private int store_area_type;
    private String store_title;
    private String store_content;
    private Long store_add_time;
    /** 推荐 */
    private String store_recommend;
    /** 实名认证 */
    private String card_approve;
    /** 实体店认证 */
    private String realstore_approve;
    /** 收藏数量 */
    private int store_favorite_count;
    /** 店铺信用 */
    private int store_credit;
    /** 级别 */
    private int store_grade;
    /** 好评率 */
    private Double store_point;
    /** 地区 */
    private Long store_area;
    /** 分类 */
    private Long store_class;

    public Long getStore_id() {
        return store_id;
    }

    public void setStore_id(Long store_id) {
        this.store_id = store_id;
    }

    public int getStore_area_type() {
        return store_area_type;
    }

    public void setStore_area_type(int store_area_type) {
        this.store_area_type = store_area_type;
    }

    public String getStore_title() {
        return store_title;
    }

    public void setStore_title(String store_title) {
        this.store_title = store_title;
    }

    public String getStore_content() {
        return store_content;
    }

    public void setStore_content(String store_content) {
        this.store_content = store_content;
    }

    public Long getStore_add_time() {
        return store_add_time;
    }

    public void setStore_add_time(Long store_add_time) {
        this.store_add_time = store_add_time;
    }

    public String getStore_recommend() {
        return store_recommend;
    }

    public void setStore_recommend(String store_recommend) {
        this.store_recommend = store_recommend;
    }

    public String getCard_approve() {
        return card_approve;
    }

    public void setCard_approve(String card_approve) {
        this.card_approve = card_approve;
    }

    public String getRealstore_approve() {
        return realstore_approve;
    }

    public void setRealstore_approve(String realstore_approve) {
        this.realstore_approve = realstore_approve;
    }

    public int getStore_favorite_count() {
        return store_favorite_count;
    }

    public void setStore_favorite_count(int store_favorite_count) {
        this.store_favorite_count = store_favorite_count;
    }

    public int getStore_credit() {
        return store_credit;
    }

    public void setStore_credit(int store_credit) {
        this.store_credit = store_credit;
    }

    public int getStore_grade() {
        return store_grade;
    }

    public void setStore_grade(int store_grade) {
        this.store_grade = store_grade;
    }

    public Double getStore_point() {
        return store_point;
    }

    public void setStore_point(Double store_point) {
        this.store_point = store_point;
    }

    public Long getStore_area() {
        return store_area;
    }

    public void setStore_area(Long store_area) {
        this.store_area = store_area;
    }

    public Long getStore_class() {
        return store_class;
    }

    public void setStore_class(Long store_class) {
        this.store_class = store_class;
    }

}

package com.gaibuy.foundation.lucene;

import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.document.Document;

public class LuceneResult {
    private List<Document> doc_list = new ArrayList<Document>();
    private List<GoodsLuceneVo> goodsVo_list = new ArrayList<GoodsLuceneVo>();
    private List<StoreLuceneVo> storeVo_list = new ArrayList<StoreLuceneVo>();
    private int pages;
    private int rows;
    private int currentPage;
    private int pageSize = 10;

    public LuceneResult(int currentPage, int pageSize) {
        this.currentPage = currentPage;
        this.pageSize = pageSize;
    }

    public List<GoodsLuceneVo> getGoodsVo_list() {
        return goodsVo_list;
    }

    public void setGoodsVo_list(List<GoodsLuceneVo> goodsVo_list) {
        this.goodsVo_list = goodsVo_list;
    }

    public List<StoreLuceneVo> getStoreVo_list() {
        return storeVo_list;
    }

    public void setStoreVo_list(List<StoreLuceneVo> storeVo_list) {
        this.storeVo_list = storeVo_list;
    }

    public List<Document> getDoc_list() {
        return doc_list;
    }

    public void setDoc_list(List<Document> doc_list) {
        this.doc_list = doc_list;
    }

    public int getPages() {
        int totalRecord = getRows();
        if (totalRecord == 0) {
            pages = 0;
        } else {
            int pageSize = getPageSize();
            pages = totalRecord % pageSize == 0 ? totalRecord / pageSize : (totalRecord / pageSize) + 1;
        }
        return this.pages;
    }

    public void setPages(int pages) {
        this.pages = pages;
    }

    public int getRows() {
        return this.rows;
    }

    public void setRows(int rows) {
        this.rows = rows;
        pages = rows / pageSize;
    }

    public int getCurrentPage() {
        if (currentPage <= 0) {
            currentPage = 1;
        } else {
            int totalPage = getPages();
            if (totalPage > 0 && currentPage > totalPage) {
                currentPage = totalPage;
            }
        }
        return this.currentPage;
    }

    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }

    public int getPageSize() {
        if (pageSize <= 0) {
            pageSize = 10;
        }
        return this.pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

}



共有 人打赏支持
粉丝 2
博文 8
码字总数 3633
评论 (1)
么么幺
不胜感激啊,解决了我ScoreDoc 无法转换FieldDoc的问题,多谢~~~
×
_sheldon
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: