io.jpress.searcher.LuceneSearcher.java Source code

Java tutorial

Introduction

Here is the source code for io.jpress.searcher.LuceneSearcher.java

Source

/**
 * Copyright (c) 2015-2016, Retire ?(wyf372310383@163.com)..
 * <p>
 * Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/lgpl-3.0.txt
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.jpress.searcher;

import com.jfinal.kit.PathKit;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Page;
import io.jpress.plugin.search.ISearcher;
import io.jpress.plugin.search.SearcherBean;
import io.jpress.utils.DateUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.lionsoul.jcseg.analyzer.v5x.JcsegAnalyzer5X;
import org.lionsoul.jcseg.tokenizer.core.JcsegTaskConfig;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

public class LuceneSearcher implements ISearcher {
    private String mIndexFilePath;

    @Override
    public void init() {
        String luceneDiskStorePath = PathKit.getWebRootPath();
        File pathFile = new File(luceneDiskStorePath, ".lucene");
        if (!pathFile.exists())
            pathFile.mkdirs();

        mIndexFilePath = pathFile.getPath();

        // ?
        try (IndexWriter indexWriter = createIndexWriter();) {

        } catch (IOException e) {
            throw new RuntimeException("LuceneSearcher init error!", e);
        }
    }

    @Override
    public void addBean(SearcherBean bean) {

        try {
            IndexWriter indexWriter = createIndexWriter();
            indexWriter.addDocument(createDocument(bean));
            indexWriter.commit();
            indexWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void deleteBean(String beanId) {
        try {
            IndexWriter indexWriter = createIndexWriter();
            Term term = new Term("sid", beanId);
            indexWriter.deleteDocuments(term);
            indexWriter.commit();
            indexWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void updateBean(SearcherBean bean) {
        try {
            IndexWriter indexWriter = createIndexWriter();
            Term term = new Term("sid", bean.getSid());
            indexWriter.updateDocument(term, createDocument(bean));
            indexWriter.commit();
            indexWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public Page<SearcherBean> search(String keyword, String module) {
        return search(keyword, module, 1, 20);
    }

    @Override
    public Page<SearcherBean> search(String queryString, String module, int pageNum, int pageSize) {
        List<SearcherBean> list = new ArrayList<SearcherBean>();
        try {
            IndexSearcher mIndexSearcher = getIndexSearcher();
            queryString = QueryParser.escape(queryString);

            String[] queries = { queryString, queryString, queryString };
            String[] fields = { "title", "description", "content" };
            BooleanClause.Occur[] flags = { BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD,
                    BooleanClause.Occur.SHOULD };
            Query query = MultiFieldQueryParser.parse(queries, fields, flags,
                    new JcsegAnalyzer5X(JcsegTaskConfig.COMPLEX_MODE));
            TopDocs topDocs = mIndexSearcher.search(query, 1000);//1000,?1000?

            if (topDocs != null && topDocs.totalHits > 0) {
                ScoreDoc[] scoreDocs = topDocs.scoreDocs;
                for (int i = 0; i < scoreDocs.length; i++) {
                    int docId = scoreDocs[i].doc;
                    Document doc = mIndexSearcher.doc(docId);
                    list.add(createSearcherBean(doc));
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return new Page<SearcherBean>(list, pageNum, pageSize, list.size() / pageSize, list.size());
    }

    public IndexWriter createIndexWriter() throws IOException {
        if (mIndexFilePath == null) {
            throw new NullPointerException("please invoke init() method first!");
        }

        Analyzer analyzer = new JcsegAnalyzer5X(JcsegTaskConfig.COMPLEX_MODE);

        // ?(?): ???
        JcsegAnalyzer5X jcseg = (JcsegAnalyzer5X) analyzer;
        // ???, ?jcseg.properties?jcseg.loadsyn=1
        JcsegTaskConfig config = jcseg.getTaskConfig();
        // ?, ?jcseg.properties?jcseg.loadpinyin=1
        config.setAppendCJKSyn(true);
        // ?, com.webssky.jcseg.core.JcsegTaskConfig
        config.setAppendCJKPinyin(true);

        Directory fsDirectory = FSDirectory.open(Paths.get(mIndexFilePath));
        IndexWriterConfig indexConfig = new IndexWriterConfig(analyzer);
        indexConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);
        indexConfig.setMaxBufferedDocs(1000);
        IndexWriter indexWriter = new IndexWriter(fsDirectory, indexConfig);
        return indexWriter;
    }

    /**
     * ?IndexReader
     *
     * @return
     */
    public IndexSearcher getIndexSearcher() {
        try {
            Directory directory = FSDirectory.open(Paths.get(mIndexFilePath));
            IndexReader ireader = DirectoryReader.open(directory);
            return new IndexSearcher(ireader);
        } catch (IOException e) {
            throw new RuntimeException("getIndexSearcher error!", e);
        }
    }

    /**
     * ?
     *
     * @param bean
     * @return
     */
    private Document createDocument(SearcherBean bean) {
        Document document = new Document();
        document.add(new TextField("content", bean.getContent(), Field.Store.YES));
        document.add(new TextField("title", bean.getTitle(), Field.Store.YES));
        document.add(new StringField("url", bean.getUrl(), Field.Store.YES));
        document.add(new TextField("description", bean.getDescription(), Field.Store.YES));
        document.add(new StringField("sid", bean.getSid(), Field.Store.YES));
        document.add(new StringField("created", DateUtils.format(bean.getCreated()), Field.Store.YES));
        return document;
    }

    /**
     * ?
     *
     * @param doc
     * @return
     */
    private SearcherBean createSearcherBean(Document doc) {
        SearcherBean searcherBean = new SearcherBean();
        String content = doc.get("content");
        String title = doc.get("title");
        String description = doc.get("description");
        String sid = doc.get("sid");
        String url = doc.get("url");
        String created = doc.get("created");
        if (StrKit.notBlank(created)) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                searcherBean.setCreated(sdf.parse(created));
            } catch (java.text.ParseException e) {
                e.printStackTrace();
            }
        }
        searcherBean.setContent(content);
        searcherBean.setTitle(title);
        searcherBean.setDescription(description);
        searcherBean.setSid(sid);
        searcherBean.setUrl(url);
        return searcherBean;
    }

}