Lucene之分页查询的三种方式-yellowcong

来源:互联网 发布:淘宝千里眼软件 编辑:程序博客网 时间:2024/05/17 22:48

分页查询有三种,一种是直接查询出这页及这页以后的数据,第二种,查询这页以前的最后一条数据,然后再查询这页之后的数据,这种方式还不如第一种方法快,第三种,是根据一个id来进行分页,这种方式适合不变更的数据

方法1

思路是将所有的查询取来,然后取自己当前页需要的数据

/**     * 创建用户:狂飙的yellowcong<br/>     * 创建日期:2017年12月3日<br/>     * 创建时间:下午3:37:17<br/>     * 机能概要: 查询所有数据后再进行分页     */    public static void queryByPager1(int pageNow,int pageSize){        IndexReader reader = null;        try {            reader = getIndexReader();            QueryParser parser = new QueryParser(Version.LUCENE_45, "content",new StandardAnalyzer(Version.LUCENE_45));            Query query = parser.parse("username:yellow*");            //创建IndexSearcher            IndexSearcher searcher = new IndexSearcher(reader);            //查询数据, 结束页面自前的数据都会查询到,但是只取本页的数据            TopDocs topDocs = searcher.search(query, pageSize*pageNow);            System.out.println("查询到的条数\t"+topDocs.totalHits);            ScoreDoc [] scores = topDocs.scoreDocs;            int start = (pageNow -1)*pageSize ;            int end = pageSize*pageNow;            for(int i=start;i<end;i++){                Document doc = reader.document(scores[i].doc);                System.out.println(doc.get("id")+":"+doc.get("username")+":"+doc.get("email"));            }        } catch (Exception e) {            e.printStackTrace();        }finally{            coloseReader(reader);        }    }

方法2

第二个方法,就是先获取前一条的记录(ScoreDoc),然后IndexSearcher.searchAfter再获取后面的记录

/**     * 创建用户:狂飙的yellowcong<br/>     * 创建日期:2017年12月3日<br/>     * 创建时间:下午3:54:55<br/>     * 机能概要:通过IndexSearcher.searchAfter     *      * @param pageNow     * @param pageSize     */    public static void queryByPager2(int pageNow, int pageSize) {        IndexReader reader = null;        try {            reader = getIndexReader();            QueryParser parser = new QueryParser(Version.LUCENE_45, "content", new StandardAnalyzer(Version.LUCENE_45));            Query query = parser.parse("username:yellow*");            // 创建IndexSearcher            IndexSearcher searcher = new IndexSearcher(reader);            int start = (pageNow - 1) * pageSize;            // 查询数据, 结束页面自前的数据都会查询到,但是只取本页的数据            TopDocs topDocs = searcher.search(query, start);            //获取到上一页最后一条            ScoreDoc preScore = topDocs.scoreDocs[start-1];            //查询最后一条后的数据的一页数据            topDocs = searcher.searchAfter(preScore, query, pageSize);            ScoreDoc[] scores = topDocs.scoreDocs;            System.out.println("查询到的条数\t" + topDocs.totalHits);            //读取数据            for (int i = 0; i < scores.length; i++) {                Document doc = reader.document(scores[i].doc);                System.out.println(doc.get("id") + ":" + doc.get("username") + ":" + doc.get("email"));            }        } catch (Exception e) {            e.printStackTrace();        } finally {            coloseReader(reader);        }    }

方法3

通过Id的方式来解决这个问题,但是id这种查询方式需要注意的是只能对不变化的数据,通过id分页,但是不能对其他的条件进行分页

/**     * 创建用户:狂飙的yellowcong<br/>     * 创建日期:2017年12月3日<br/>     * 创建时间:下午2:38:27<br/>     * 机能概要:分页查询     *      * @param pageSize     * @param pageNow     * @throws Exception     */    public static void queryByPager3(int pageNow, int pageSize) {        IndexReader reader = null;        try {            reader = getIndexReader();            Query query = NumericRangeQuery.newIntRange("id", (pageNow - 1) * pageSize + 1, pageNow * pageSize, true,                    true);            // 创建IndexSearcher            IndexSearcher searcher = new IndexSearcher(reader);            // 查询数据            TopDocs topDocs = searcher.search(query, pageSize);            for (ScoreDoc score : topDocs.scoreDocs) {                Document doc = reader.document(score.doc);                System.out.println(doc.get("id") + ":" + doc.get("username") + ":" + doc.get("email"));            }        } catch (Exception e) {            e.printStackTrace();        } finally {            coloseReader(reader);        }    }

完整代码

package com.yellowcong.demo;import java.io.File;import java.io.IOException;import java.util.ArrayList;import java.util.Date;import java.util.List;import org.apache.lucene.analysis.standard.StandardAnalyzer;import org.apache.lucene.document.Document;import org.apache.lucene.document.Field;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.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.QueryParser;import org.apache.lucene.search.FuzzyQuery;import org.apache.lucene.search.IndexSearcher;import org.apache.lucene.search.NumericRangeQuery;import org.apache.lucene.search.PhraseQuery;import org.apache.lucene.search.PrefixQuery;import org.apache.lucene.search.Query;import org.apache.lucene.search.ScoreDoc;import org.apache.lucene.search.TermQuery;import org.apache.lucene.search.TopDocs;import org.apache.lucene.search.WildcardQuery;import org.apache.lucene.store.FSDirectory;import org.apache.lucene.util.Version;/** * 创建用户:狂飙的yellowcong<br/> * 创建时间:下午5:27:50<br/> * 创建日期:2017年12月2日<br/> * 机能概要: */public class Demo6 {    private static List<Passage> psgList = null;    // 写对象    private static IndexWriter writer = null;    public static void main(String[] args) throws Exception {        // 删除 所有索引        deleteAll();        // 建立索引        index();        queryByPager3(3, 10);    }    /**     * 创建用户:狂飙的yellowcong<br/>     * 创建日期:2017年12月3日<br/>     * 创建时间:下午3:54:55<br/>     * 机能概要:通过IndexSearcher.searchAfter     *      * @param pageNow     * @param pageSize     */    public static void queryByPager2(int pageNow, int pageSize) {        IndexReader reader = null;        try {            reader = getIndexReader();            QueryParser parser = new QueryParser(Version.LUCENE_45, "content", new StandardAnalyzer(Version.LUCENE_45));            Query query = parser.parse("username:yellow*");            // 创建IndexSearcher            IndexSearcher searcher = new IndexSearcher(reader);            int start = (pageNow - 1) * pageSize;            // 查询数据, 结束页面自前的数据都会查询到,但是只取本页的数据            TopDocs topDocs = searcher.search(query, start);            //获取到上一页最后一条            ScoreDoc preScore = topDocs.scoreDocs[start-1];            //查询最后一条后的数据的一页数据            topDocs = searcher.searchAfter(preScore, query, pageSize);            ScoreDoc[] scores = topDocs.scoreDocs;            System.out.println("查询到的条数\t" + topDocs.totalHits);            //读取数据            for (int i = 0; i < scores.length; i++) {                Document doc = reader.document(scores[i].doc);                System.out.println(doc.get("id") + ":" + doc.get("username") + ":" + doc.get("email"));            }        } catch (Exception e) {            e.printStackTrace();        } finally {            coloseReader(reader);        }    }    /**     * 创建用户:狂飙的yellowcong<br/>     * 创建日期:2017年12月3日<br/>     * 创建时间:下午3:37:17<br/>     * 机能概要: 查询所有数据后再进行分页     */    public static void queryByPager1(int pageNow, int pageSize) {        IndexReader reader = null;        try {            reader = getIndexReader();            QueryParser parser = new QueryParser(Version.LUCENE_45, "content", new StandardAnalyzer(Version.LUCENE_45));            Query query = parser.parse("username:yellow*");            // 创建IndexSearcher            IndexSearcher searcher = new IndexSearcher(reader);            // 查询数据, 结束页面自前的数据都会查询到,但是只取本页的数据            TopDocs topDocs = searcher.search(query, pageSize * pageNow);            // searcher.searchAfter(after, query, n)            System.out.println("查询到的条数\t" + topDocs.totalHits);            ScoreDoc[] scores = topDocs.scoreDocs;            int start = (pageNow - 1) * pageSize;            int end = pageSize * pageNow;            for (int i = start; i < end; i++) {                Document doc = reader.document(scores[i].doc);                System.out.println(doc.get("id") + ":" + doc.get("username") + ":" + doc.get("email"));            }        } catch (Exception e) {            e.printStackTrace();        } finally {            coloseReader(reader);        }    }    /**     * 创建用户:狂飙的yellowcong<br/>     * 创建日期:2017年12月3日<br/>     * 创建时间:下午2:38:27<br/>     * 机能概要:分页查询     *      * @param pageSize     * @param pageNow     * @throws Exception     */    public static void queryByPager3(int pageNow, int pageSize) {        IndexReader reader = null;        try {            reader = getIndexReader();            Query query = NumericRangeQuery.newIntRange("id", (pageNow - 1) * pageSize + 1, pageNow * pageSize, true,                    true);            // 创建IndexSearcher            IndexSearcher searcher = new IndexSearcher(reader);            // 查询数据            TopDocs topDocs = searcher.search(query, pageSize);            for (ScoreDoc score : topDocs.scoreDocs) {                Document doc = reader.document(score.doc);                System.out.println(doc.get("id") + ":" + doc.get("username") + ":" + doc.get("email"));            }        } catch (Exception e) {            e.printStackTrace();        } finally {            coloseReader(reader);        }    }    /**     * 创建用户:狂飙的yellowcong<br/>     * 创建日期:2017年12月3日<br/>     * 创建时间:下午12:01:55<br/>     * 机能概要:查询Query 将需要查询的条件传递进来     *      * @param query     */    public static void excQuery(Query query) {        // 查询        IndexReader reader = null;        try {            reader = getIndexReader();            // 获取查询数据            IndexSearcher searcher = new IndexSearcher(reader);            // 检索数据            TopDocs topDocs = searcher.search(query, 100);            for (ScoreDoc scoreDoc : topDocs.scoreDocs) {                // 湖区偶                Document doc = reader.document(scoreDoc.doc);                System.out.println(doc.get("id") + ":" + doc.get("username") + ":" + doc.get("email"));            }        } catch (Exception e) {            e.printStackTrace();        } finally {            coloseReader(reader);        }    }    /**     * 创建用户:狂飙的yellowcong<br/>     * 创建日期:2017年12月3日<br/>     * 创建时间:上午11:52:52<br/>     * 机能概要:关闭IndexReader     *      * @param reader     */    private static void coloseReader(IndexReader reader) {        try {            if (reader != null) {                reader.close();            }        } catch (IOException e) {            e.printStackTrace();        }    }    static {        psgList = new ArrayList<Passage>();        // 产生一堆数据        for (int i = 1; i <= 200; i++) {            psgList.add(new Passage(i, "yellowcong", "717350389@qq.com", "逗比", 23, "I LOVE YOU ", new Date()));        }    }    /**     * 创建用户:狂飙的yellowcong<br/>     * 创建日期:2017年12月2日<br/>     * 创建时间:下午5:43:57<br/>     * 机能概要:获取IndexWriter 同一时间 ,只能打开一个 IndexWriter,独占写锁 。内建线程安全机制。     *      * @return     * @throws Exception     */    @SuppressWarnings("static-access")    public static IndexWriter getIndexWriter() throws Exception {        // 创建IdnexWriter        String path = getIndexPath();        FSDirectory fs = FSDirectory.open(new File(path));        // 判断资源是否占用        if (writer == null || !writer.isLocked(fs)) {            synchronized (Demo3.class) {                if (writer == null || !writer.isLocked(fs)) {                    // 创建writer对象                    writer = new IndexWriter(fs,                            new IndexWriterConfig(Version.LUCENE_45, new StandardAnalyzer(Version.LUCENE_45)));                }            }        }        return writer;    }    /**     * 创建用户:狂飙的yellowcong<br/>     * 创建日期:2017年12月2日<br/>     * 创建时间:下午5:46:36<br/>     * 机能概要:获取到IndexReader 任意多个IndexReaders可同时打开,可以跨JVM。     *      * @return     * @throws Exception     */    public static IndexReader getIndexReader() throws Exception {        // 创建IdnexWriter        String path = getIndexPath();        FSDirectory fs = FSDirectory.open(new File(path));        // 获取到读        return IndexReader.open(fs);    }    /**     * 创建用户:狂飙的yellowcong<br/>     * 创建日期:2017年12月2日<br/>     * 创建时间:下午7:57:04<br/>     * 机能概要:删除所有的索引     */    public static void deleteAll() {        IndexWriter writer = null;        try {            // 获取IndexWriter            writer = getIndexWriter();            // 删除所有的数据            writer.deleteAll();            int cnt = writer.numDocs();            System.out.println("索引条数\t" + cnt);            // 提交事物            writer.commit();        } catch (Exception e) {            e.printStackTrace();        } finally {            coloseWriter(writer);        }    }    /**     * 创建用户:狂飙的yellowcong<br/>     * 创建日期:2017年12月2日<br/>     * 创建时间:下午5:37:22<br/>     * 机能概要:获取索引目录     *      * @return 目录     */    private static String getIndexPath() {        // 获取索引的目录        String path = Demo3.class.getClassLoader().getResource("index").getPath();        // 不存在就创建目录        File file = new File(path);        if (!file.exists()) {            file.mkdirs();        }        return path;    }    /**     * 创建用户:狂飙的yellowcong<br/>     * 创建日期:2017年12月2日<br/>     * 创建时间:下午8:24:16<br/>     * 机能概要:关闭IndexWriter     */    private static void coloseWriter(IndexWriter writer) {        try {            if (writer != null) {                writer.close();            }        } catch (IOException e) {            e.printStackTrace();        }    }    /**     * 创建用户:狂飙的yellowcong<br/>     * 创建日期:2017年12月2日<br/>     * 创建时间:下午8:26:15<br/>     * 机能概要:关闭IndexReader     *      * @param reader     */    public static void closerReader(IndexReader reader) {        try {            if (reader != null) {                reader.close();            }        } catch (IOException e) {            e.printStackTrace();        }    }    /**     * 创建用户:狂飙的yellowcong<br/>     * 创建日期:2017年12月2日<br/>     * 创建时间:下午8:10:01<br/>     * 机能概要: 查询数据     *      * @param key     *            查询范围     * @param val     *            值     */    public static void search(String key, Object val) {        IndexReader reader = null;        try {            reader = getIndexReader();            IndexSearcher searcher = new IndexSearcher(reader);            // 精确查询            Query query = null;            // 定义查询条件            if (val instanceof Integer) {                // 后面的两个true 表示的是 是否包含 上下的数据                query = NumericRangeQuery.newIntRange(key, Integer.parseInt(val.toString()),                        Integer.parseInt(val.toString()), true, true);            } else {                query = new TermQuery(new Term(key, val.toString()));            }            // QueryParser paraser = new QueryParser(Version.LUCENE_45, key, new            // StandardAnalyzer(Version.LUCENE_45));            // Query query = paraser.parse(val);            // 获取查询到的Docuemnt            TopDocs topDocs = searcher.search(query, 500);            // 总共命中的条数            System.out.println(topDocs.totalHits);            for (ScoreDoc score : topDocs.scoreDocs) {                //                Document doc = searcher.doc(score.doc);                // 查询到的结果                String username = doc.get("username");                System.out.println(username);            }        } catch (Exception e) {            e.printStackTrace();        } finally {            closerReader(reader);        }    }    /**     * 创建用户:狂飙的yellowcong<br/>     * 创建日期:2017年12月2日<br/>     * 创建时间:下午6:03:33<br/>     * 机能概要:建立索引     */    public static void index() {        IndexWriter writer = null;        try {            // 1、获取IndexWriter            writer = getIndexWriter();            // 2、建立索引            for (Passage psg : psgList) {                Document doc = new Document();                // IntField 不能直接检索到,需要结合                doc.add(new IntField("id", psg.getId(), Field.Store.YES));                // 用户String类型的字段的存储,StringField是只索引不分词                doc.add(new TextField("username", psg.getUsername(), Field.Store.YES));                // 主要对int类型的字段进行存储,需要注意的是如果需要对InfField进行排序使用SortField.Type.INT来比较,如果进范围查询或过滤,需要采用NumericRangeQuery.newIntRange()                doc.add(new IntField("age", psg.getAge(), Field.Store.YES));                // 对String类型的字段进行存储,TextField和StringField的不同是TextField既索引又分词                doc.add(new TextField("content", psg.getContent(), Field.Store.NO));                doc.add(new StringField("keyword", psg.getKeyword(), Field.Store.YES));                doc.add(new StringField("email", psg.getEmail(), Field.Store.YES));                // 日期数据添加索引                doc.add(new LongField("addDate", psg.getAddDate().getTime(), Field.Store.YES));                // 3、添加文档                writer.addDocument(doc);            }            // 索引条数            int cnt = writer.numDocs();            System.out.println("索引条数\t" + cnt);            // 提交事物            writer.commit();        } catch (Exception e) {            e.printStackTrace();        } finally {            coloseWriter(writer);        }    }    static class Passage {        private int id;        private String username;        private String email;        private String keyword;        private int age;        // 这个模拟的是文章        private String content;        private Date addDate;        public Passage(int id, String username, String email, String keyword, int age, String content, Date addDate) {            super();            this.id = id;            this.username = username;            this.email = email;            this.keyword = keyword;            this.age = age;            this.content = content;            this.addDate = addDate;        }        public int getId() {            return id;        }        public void setId(int id) {            this.id = id;        }        public String getUsername() {            return username;        }        public void setUsername(String username) {            this.username = username;        }        public String getEmail() {            return email;        }        public void setEmail(String email) {            this.email = email;        }        public String getKeyword() {            return keyword;        }        public void setKeyword(String keyword) {            this.keyword = keyword;        }        public int getAge() {            return age;        }        public void setAge(int age) {            this.age = age;        }        public String getContent() {            return content;        }        public void setContent(String content) {            this.content = content;        }        public Date getAddDate() {            return addDate;        }        public void setAddDate(Date addDate) {            this.addDate = addDate;        }    }}
阅读全文
0 0
原创粉丝点击