Solr学习整理(Luncene原理)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Solr学习整理(Luncene原理)相关的知识,希望对你有一定的参考价值。

  由于各种原因大概很长时间都要折腾solr了,既来之则安之,花了好多精力折腾的项目怎么能不好好整理学习一下,深入理解一下solr的原理。目前接触到的搜索相关的几乎就是solr和elasticsearch平分天下,而这两者由都是基于luncene开发的全文检索系统,elasticsearch暂时还没有接触,暂时被solr虐的死去活来。

  什么是luncene? Luncene是java开发的信息检索类库,专注于文本的搜索和索引,对文本中提取出来的数据进行索引和检索,也就是说luncene提供了全文检索的两个核心功能,索引和检索,而其他的则需要用户自己实现,如solr和elasticsearch就是各自基于luncene的实现。

  Luncene的索引是什么? Lunecen的索引本质上是一种倒排索引,倒排索引的功能是快速的返回要查找的单词包含在哪些文档中。

  luncene的索引过程?索引的基本单位是文档,一个文档可以包含多个域,域值可以被索引也可以被单独存值,Luncene的索引过程就是从原始的文本中提取数据,并创建对应的document实例,一个document中包含了多个域,域是用来保存原始数据,然后分析过程将域处理成语汇单元添加到段文件中,核心过程可以总结成为,提取文档,分析文档,添加文档三个过程。提取文档过程,从各种文本中提取数据,对应的程序指的就是封装document的过程,分析文档,将要索引的数据封装成一个个的document对象之后会交给luncene来分析,分析过程会将数据分割成一个个的语汇单元,并做一些处理,比如对数据进行大小写转换,去除一些停词,无意义的词,最后生成语汇单元,最后对生成语汇单元写入到索引文件中。

技术分享

 

  来写一个对本地文件夹所有文件建索引的程序,对F盘下的所有文件的文件名建索引,生成的索引存放在F:\\\\Lucence\\\\Fdiskindex 目录下

  添加pom依赖

  

 <lucene.version>4.6.1</lucene.version>  


<dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-core</artifactId>
            <version>${lucene.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-analyzers-common</artifactId>
            <version>${lucene.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-queryparser</artifactId>
            <version>${lucene.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.lucene/lucene-highlighter -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-highlighter</artifactId>
            <version>${lucene.version}</version>
        </dependency>

f盘文件建索引

public class DiskIndex {

    private static Logger logger = Logger.getLogger(DiskIndex.class);

    private String IndexOutputStr;

    private String indexRootPath;

    public String getIndexOutputStr() {
        return IndexOutputStr;
    }

    public void setIndexOutputStr(String indexOutputStr) {
        IndexOutputStr = indexOutputStr;
    }

    public String getIndexRootPath() {
        return indexRootPath;
    }

    public void setIndexRootPath(String indexRootPath) {
        this.indexRootPath = indexRootPath;
    }

    private IndexWriter iwriter;

    public void index() {
        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_46);
        IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_46, analyzer);
        try {
            Directory directory = FSDirectory.open(new File(IndexOutputStr));
            iwriter = new IndexWriter(directory, config);
            File inputfile = new File(indexRootPath);
            File[] files = inputfile.listFiles();
            for (File file : files) {
                if(fileFilter(file)) {
                    addDoc(file);
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
            logger.warn("打开文件异常");
        }
    }

    private void addDoc(File file) {
        if (file.isDirectory()&&(!file.getPath().contains("RECYCLE.BIN"))) {
            try{
            File[]  filelist = file.listFiles();
            for ( File afile: filelist ) {
            addDoc(afile);
            } }catch (Exception E){

            }

        } else if (file.isFile()&&(!file.getPath().contains("RECYCLE.BIN"))) {
            try {
                indexFile(file);
            } catch (IOException e) {
                logger.info("索引文件出错 path = " + file.getPath());
            }
        }
    }

    private void close() throws IOException {
        iwriter.close();
    }

    private void indexFile(File file) throws IOException {
        logger.info(" index file = "+ file.getPath());
        String fileName = file.getName();
        String filePath = file.getPath();
        Long fileSize = file.length();
        Document doc = new Document();
        doc.add(new Field("filename", fileName, TextField.TYPE_STORED));
        doc.add(new Field("filepath", filePath, TextField.TYPE_STORED));
        doc.add(new LongField("fileSize", fileSize, LongField.TYPE_STORED));
        iwriter.addDocument(doc);

    }

    public static  boolean fileFilter(File file){
        Boolean  flag = true;
        if(file.getPath().contains("spark")){
            flag = false;
        }
        if(file.getPath().contains("hive")){
            flag = false;
        }
        return flag;
    }
     public static void main(String[] args) throws IOException {
        DiskIndex index = new DiskIndex();
        index.setIndexRootPath("F:\\\\");
        index.setIndexOutputStr("F:\\\\Lucence\\\\Fdiskindex");
        index.index();
        index.close();
     }

}

再来一个搜索程序,搜索F盘下和redis有关的文件

public class DiskSearch {

    private Logger logger = Logger.getLogger(DiskIndex.class);

    private DirectoryReader ireader = null;

    private IndexSearcher isearcher = null;

    private String indexdir = "F:\\\\Lucence\\\\Fdiskindex";

    public void search(String queryField) {

        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_46);
        QueryParser parser = new QueryParser(Version.LUCENE_46, "filename", analyzer);
        Directory directory = null;
        try {
            directory = FSDirectory.open(new File(indexdir));
            DirectoryReader ireader = DirectoryReader.open(directory);
            IndexSearcher isearcher = new IndexSearcher(ireader);

            Query query = parser.parse(queryField);//query  word
            ScoreDoc[] hits = isearcher.search(query, null, 1000).scoreDocs;
            for (int i = 0; i < hits.length; i++) {
                Document hitDoc = isearcher.doc(hits[i].doc);
                System.out.println("____________________________");
                System.out.println(hitDoc.get("filename"));
                System.out.println(hitDoc.get("filepath"));
            }
            ireader.close();
            directory.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        DiskSearch  search = new DiskSearch();
        search.search("redis");
    }

}

 

查看返回结果

技术分享

 

 

 

  

以上是关于Solr学习整理(Luncene原理)的主要内容,如果未能解决你的问题,请参考以下文章

Solr

solr 学习片段

ElasticSearch原理架构

IOS开发-OC学习-常用功能代码片段整理

solr分布式索引实战分片配置读取:工具类configUtil.java,读取配置代码片段,配置实例

solrcloud配置中文分词器ik