美文网首页
Lucene Manual

Lucene Manual

作者: Herman7z | 来源:发表于2018-03-22 14:38 被阅读0次

1. 索引

注意:在建立索引以后,内容的所有大写字母全部被转化为小写;索引更新实际是先删除原来的后创建新的

1) 存储域选项:

Field.Store.YES 或者 NO
设置为YES表示或把这个域中的内容完全存储到文件中,方便进行文本的还原
设置为NO表示把这个域的内容不存储到文件中,但是可以被索引,内容无法还原

2) 索引域选项:

Field.Index
Index.ANALYZED : 进行分词和索引,适用于标题、内容等
Index.NOT_ANALYZED : 进行索引,但是不进行分词,如果身份证,姓名,ID等,适用于精确搜索
Index.ANALYZED_NOT_NORMS : 进行分词但是不存储norms信息,这个norms中包括了创建索引的时间和权值等信息
Index.NOT_ANALYZED_NOT_NORMS : 即不进行分词也不存储norms信息
Index.NO : 不进行索引

3) 给数字和日期索引

给数字添加索引:NumericField -> new NumericField("attachs", Field.Store.YES, true).setIntValue(attachs[i])
给日期添加索引:NumericField -> new NumericField("date", Field.Store.YES, true).setLongValue(dates[i].getTime())

4) IndexReader设计

IndexReader:打开和关闭都很耗时,通常设置为单例,在类初始化时候创建,使用之后都不要关闭
IndexSearcher:通过IndexReader创建,每次使用完成后需要关闭
注意:
IndexReader是单例的,当IndexWriter修改了索引之后,已经打开的IndexReader是不会更新修改的索引,只有重新打开IndexReader才会更新
解决办法:创建一个获取reader的方法,方法中代码如下
IndexReader newReader = IndexReader.openIfChanged(oldReader);//若发生了改变,那么就返回一个新的reader,否则返回null
if(newReader != null) { reader.close();oldReader = newReader;}//关闭原来的reader,重新赋值
IndexReader也可以执行删除操作,好处是删除了索引后,reader能够马上就知道,避免使用openIfChanged方法

5) IndexWriter设计

同IndexReader一样设置为单例,每次使用完成后不关闭,调用writer.commit()提交本次操作的改变

6) Directory

FSDirectory:索引存储到硬盘中
RAMDirectory:索引存储到内存中,可以根据硬盘中的索引创建
FSDirectory.open会根据当前的运行环境打开一个最合理的基于File的Directory
RAMDirectory会从内存中打开directory,好处是速度快,缺点是无法持久化


2. 搜索

1) 精确匹配查询 (TermQuery)

IndexSearcher searcher = getSearcher();
Query query = new TermQuery(new Term(field, value));
TopDocs topDocs = searcher.search(query, num);
System.out.println("totalHits:" + topDocs.totalHits);//显示共有多少匹配项,这个和 查询num 没有关系

2) 范围查询(TermRangeQuery)

field:域
lowerTerm:开始范围
upperTerm:结束范围
includeLower:包含开区间
includeUpper:包含闭区间
new TermRangeQuery(String field, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper)
注意:这种查询方式无法查询数字类型的域

3) 数字范围查询(NumericRangeQuery)

field:域
min:开始范围
max:结束范围
minInclusive:包含开区间
maxInclusive:包含闭区间
NumericRangeQuery.newIntRange(String field, Integer min, Integer max, boolean minInclusive, boolean maxInclusive)

4) 前缀查询(PrefixQuery)

new PrefixQuery(new Term(field, value))

5) 通配符查询(WildcardQuery)
  • : 任意多个字符
    ? : 任意一个字符
    new WildcardQuery(new Term(field, value))
5) 组合查询(BooleanQuery)

BooleanQuery query = new BooleanQuery(); //可以连接多个子查询
query.add(new WildcardQuery(new Term("name", "j*")), BooleanClause.Occur.MUST);
query.add(new TermQuery(new Term("content", "like")), BooleanClause.Occur.MUST);
Occur.MUST 必须出现
Occur.SHOULD 可以出现
Occur.MUST_NOT 不能出现

6) 短语查询(PhraseQuery)

PhraseQuery query = new PhraseQuery();
query.setSlop(1); //设置中间跳过的短语数
query.add(new Term("content", "i")); //设置前一个短语
query.add(new Term("content", "football")); //设置后一个短语

7) 模糊查询(FuzzyQuery)

查询相似度最接近的

8) QueryParser:使用较多
a. 创建时设置版本,默认查询的域,分词器
QueryParser queryParser = new QueryParser(Version.LUCENE_35, "content", new StandardAnalyzer(Version.LUCENE_35));
b. 设置要查询的字符串,默认字符串被分词,每个词查询的结果被组合到了一起,可以通过一下方式设置查询结果的组合方式
queryParser.setDefaultOperator(QueryParser.Operator.AND);
Query query = queryParser.parse("like basketball");
c. 查询的时候指定查询域:
Query query = queryParser.parse("name:mike");
d. 使用通配符:
Query query = queryParser.parse("name:j*");
开启查询字符串首字母通配符匹配,默认是关闭的  效率低
queryParser.setAllowLeadingWildcard(true);
e. queryParser.parse("- name:mike + football"); //注意空格
- : 不包含
+ : 包含
f. query =queryParser.parse("id:[1 TO 3]"); 匹配一个区域,TO必须大写,开区间匹配 1,2,3
query = queryParser.parse("id:{1 TO 3}");  

匹配一个区域,TO必须大写,闭区间匹配 2
注意:TO这种方式不能匹配数字,只适用于字符串

g. AND,OR使用
query = queryParser.parse("(mike OR john) AND address:xinde"); 名字有mike或者john,地址是xinde
h. 多个词整体匹配
query = queryParser.parse("\"i like football\"");
等同于
query = queryParser.parse("i AND like AND football");
i. query = queryParser.parse(""i football"~1"); 匹配 i 和 football 之间有一个单词
j. query = queryParser.parse("name:make~"); 模糊查询
9) Lucene分页查询

不支持类似数据库的分页方式;(再查询)

  1. 每次都会查询出所有的数据,然后在取出每一页的数据,查询的速度已经很快,不用担心性能
  2. 使用searchAfter方法(推荐)
private ScoreDoc getLastScoreDoc(int page, int size, Query query, IndexSearcher searcher) throws IOException {    //获取出上一页的最后一个元素ScoreDoc
    if (page == 1) return null;
    int num = (page - 1) * size;  //从0开始  每次只取需要的数据
    TopDocs topDocs = searcher.search(query, num);
    return topDocs.scoreDocs[num - 1];
}

public void searchPageByAfter(String query, int page, int size) throws ParseException, IOException {
    IndexSearcher searcher = this.getSearcher();
    QueryParser parser = new QueryParser(Version.LUCENE_35, "content", new StandardAnalyzer(Version.LUCENE_35));
    Query q = parser.parse(query);
    ScoreDoc lastScoreDoc = getLastScoreDoc(page, size, q, searcher);//获取上一页的最后一个元素
    TopDocs topDocs = searcher.searchAfter(lastScoreDoc, q, size); //通过上一页的最后一个元素搜索下一页
    for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
        Document doc = searcher.doc(scoreDoc.doc);
        System.out.println(scoreDoc.doc + "->" + doc.get("path"));
    }
}

3. 分词

1) 3.5版本推荐的分词器:SimpleAnalyzer,StandardAnalyzer,StopAnalyzer,WhitespaceAnalyzer
2) 分词调用顺序:采用的是责任链模式,首先调用一系列的TokenFilter -> Tokenizer把输入的内容分词一个词组 ->回到TokenFilter,处理解析出来的词组

4. 排序

1) Sort

Sort.INDEXORDER :以文档编号排序 doc的id eg: searchUtils.search("java", Sort.INDEXORDER);
Sort.RELEVANCE :使用默认的评分排序 eg: searchUtils.search("java", Sort.RELEVANCE);

2) SortField 指定域排序

searchUtils.search("java", new Sort(new SortField("size",SortField.INT)); //文件大小排序
searchUtils.search("java", new Sort(new SortField("date",SortField.LONG)); //文件创建日期排序
searchUtils.search("java", new Sort(new SortField("filename",SortField.STRING)); //文件名排序
searchUtils.search("java", new Sort(new SortField("filename",SortField.STRING,true)); //文件名反转排序
searchUtils.search("java", new Sort(new SortField("size",SortField.INT),SortField.FIELD_SCORE); //先通过文件大小排序,后通过文件评分排序

5. 过滤Filter

1) TermRangeFilter 范围过滤

Filter filter = new TermRangeFilter("filename", "java.hhh", "java.kkk", true, true);
searchUtils.search("java", filter);

2) NumericRangeFilter 数字范围过滤

Filter filter =NumericRangeFilter.newIntRange("size", 500, 900, true, true);
searchUtils.search("java", filter);

3) QueryWrapperFilter 可以通过一个Query过滤

Filter filter =new QueryWrapperFilter(new WildcardQuery(new Term("filename","*.txt")));
searchUtils.search("java", filter);

6. 自定义评分

  1. 步骤:
    1.创建一个类继承于CustomScoreQuery
    2.覆盖getCustomScoreProvider
    3.创建CustomScoreProvider类
    4.覆盖customScore

相关文章

  • Lucene Manual

    1. 索引 注意:在建立索引以后,内容的所有大写字母全部被转化为小写;索引更新实际是先删除原来的后创建新的 1) ...

  • Lucene 7.4 初体验

    前言 本文的简要内容: Lucene简介 体验Lucene Demo Lucene 核心类介绍 Lucene 索引...

  • Lucene 构造索引 & 查询 Demo

    maven引入lucene-core,lucene-analyzers-common,lucene-querypa...

  • Elasticsearch | Lucene概要

    核心要点:1、Lucene简介2、Lucene的优点3、文档自动解析流程4、Lucene架构5、Lucene的基本...

  • [转]Lucene的索引文件格式

    原文链接Lucene学习总结之三:Lucene的索引文件格式(1)、Lucene的索引文件格式(2)、Lucene...

  • Lucene的索引文件格式(基于V7_3_0)

    拜读刘超觉先的Lucene学习笔记Lucene学习总结之三:Lucene的索引文件格式(1)、Lucene的索引文...

  • Elasticsearch

    Elasticsearch 一.全文检索和Lucene Lucene基于java环境,基于Lucene之上包装一层...

  • 生成器

    PHP Manual手册对于生成器的概述:PHP Manual Generator PHP Manual手册新特性...

  • Lucene编译

    编译 直接在lucene-solr目录下执行:ant compile 到lucene-solr/lucene目录下...

  • solr4.10.3集成tomcat

    从lucene的官方下载,lucene和solr的版本是同步更新的:http://lucene.apache.or...

网友评论

      本文标题:Lucene Manual

      本文链接:https://www.haomeiwen.com/subject/zgeaqftx.html