lucene 入门整理

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

1.    概述

Lucene是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎。Lucene以其方便使用、快速实施以及灵活性受到广泛的关注。它可以方便地嵌入到各种应用中实现针对应用的全文索引、检索功能,本总结使用lucene--2.3.2。

2.    lucene 的包结构

1、org.apache.lucene.analysis对需要建立索引的文本进行分词、过滤等操作, 语言分析器,主要用于的切词Analyzer是一个抽象类,管理对文本内容的切分词规则。

2、org.apache.lucene.analysis.standard是标准分析器

3、org.apache.lucene.document提供对Document和Field的各种操作的支持。索引存储时的文档结构管理,类似于关系型数据库的表结构。Document相对于关系型数据库的记录对象,Field主要负责字段的管理。

4、org.apache.lucene.index是最重要的包,用于向Lucene提供建立索引时各种操作的支持。索引管理,包括索引建立、删除等。索引包是整个系统核心,全文检索的根本就是为每个切出来的词建索引,查询时就只需要遍历索引,而不需要去正文中遍历,从而极大的提高检索效率。

5、org.apache.lucene.queryParser提供检索时的分析支持。查询分析器,实现查询关键词间的运算,如与、或、非等。

6、org.apache.lucene.search 负责检索。检索管理,根据查询条件,检索得到结果。

7、org.apache.lucene.store提供对索引存储的支持。数据存储管理,主要包括一些底层的I/0操作。

8、org.apache.lucene.util提供一些常用工具类和常量类的支持

3.    索引文件格式

a)         .fnm格式  包含了Document中所有field名称

b)        .fdt与.fdx格式  .fdt文件用于存储具有Store.YES属性的Field的数据;.fdx是一个索引,用于存储Document在.fdt中的位置。

c)         .tis 与.tii格式  .tis文件用于存储分词后的词条(Term),而.tii就是它的索引文件,它表明了每个.tis文件中的词条的位置。

d)        deletable格式 文档被删除后,会首先在deletable文件中留下一个记录,要真正删除时,才将索引除去。

e)         复合索引格式 .cfs

使用IndexWriter的useCompoundFile()  默认为True

4.    lucene中主要的类

4.1. Document文档类

4.1.1.常用方法

方法

描述

void add(Field field)

Document对象中添加字段

void removeField(String name)

删除字段。若多个字段以同一个字段名存在,则删除首先添加的字段;若不存在,则Document保持不变

void removeFields(String name)

删除所有字段。若字段不存在,则Document保持不变

Field getFieldString name

若多个字段以同一个字段名存在,则返回首先添加的字段;若字段不存在,则Document保持不变

Enumeration fields()

返回Document对象的所有字段,以枚举类型返回

Field [] getFields(String name)

根据名称得到一个Field的数组

String [] getValues(String name)

根据名称得到一个Field的值的数组

 

4.1.2.示例

Document doc1 = new Document();

doc1.add(new Field("name", "word1 word2 word3",

Field.Store.NO,Field.Index.TOKENIZED));

Document doc2 = new Document();

doc2.add(new Field("name", "word1 word2 word3",

Field.Store.NO,Field.Index.TOKENIZED));

4.2. Field字段类

4.2.1.构造方法

1)        public Field(String name,String value,Store store,Index index);//直接的字符串方式

2)        public Field(String name,String value,Store store,Index index,TermVector termVector);

3)        public Field(String name,String value,Reader reader);//使用Reader从外部传入

4)        public Field(String name,String value,Reader reader,TermVector termVector);

5)        public Field(String name,byte[] value,Store store)//使用直接的二进制byte传入

当Field值为二进制时,可以使用Lucene的压缩功能将其值进行压缩。

4.2.2.Store类

静态属性

描述

Store.NO

表示该Field不需要存储

Store.YES

表示该Field需要存储

Store.COMPRESS

表示用压缩方式来保存这个Field的值

4.2.3.Index类

静态属性

描述

Index.NO

不需要索引

Index.TOKENIZED

先被分词再被索引

Index.UN_TOKENIZED

不对该Field进行分词,但会对它进行索引

Index.NO_NORMS

对该Field进行索引,但是不使用Analyzer,同时禁止它参加评分,主要是为了减少内存的消耗。

 

4.2.4.示例

new Field("name", "word1 word2 word3",Field.Store.YES,Field.Index.TOKENIZED)

 

4.3. IndexWriter类

4.3.1.构造方法

1)        public IndexWriter(String path,Analyzer a,Boolean create)

2)        public IndexWriter(File path,Analyzer a,Boolean create)

3)        public IndexWriter(Directory d,Analyzer a,Boolean create)

第一个参数:索引存放在什么地方

第二个参数:分析器,继承自org.apache.lucene.analysis.Analyzer类

第三个参数:为true时,IndexWriter不管目录内是否已经有索引了,一律清空,重新建立;当为false时,则IndexWriter会在原有基础上增量添加索引。所以在更新的过程中,需要设置该值为false。

4.3.2.添加文档

public void addDocument(Document doc)

public void addDocument(Document doc,Analyzer analyzer)//使用一个开发者自定义的,而非事先在构建IndexWriter时声明的Analyzer来进行分析

writer.addDocument(doc1);

4.3.3.性能参数

1)        mergeFactor控制Lucene在把索引从内存写入磁盘上的文件系统时内存中最大的Document数量,同时它还控制内存中最大的Segment数量。默认为10.

writer.setMergeFactor(10);

2)        maxMergeDocs限制一个Segment中最大的文档数量。一个较大的maxMergeDocs适用于对大批量的文档建立索引,增量式的索引则应使用较小的maxMergeDocs。

writer.setMaxMergeDocs(1000);

3)        minMergeDocs用于控制内存中持有的文档数量的,它对磁盘上的Segment大小没有任何影响。

4.3.4.限制Field的长度

maxFieldLength限制Field的长度,默认值为10000.最大值100000个。

public void setMaxFieldLength(int maxFieldLength)

writer.addDocument(doc1);

writer.setMaxFieldLength(100000);

writer.addDocument(doc2);

4.3.5.复合索引格式

setUseCompoundFile(Boolean) 默认true

writer.setUseCompoundFile(true);//复合索引

writer.setUseCompoundFile(false);

4.3.6.优化索引

writer.optimize();

将磁盘上的多个segment进行合并,组成一个全新的segment。这种方法并不会增加建索时的速度,反而会降低建索的速度。所以应该在建完索引后在调用这个函数

4.3.7.示例

IndexWriter writer = new IndexWriter(path, new StandardAnalyzer(), true);

writer.addDocument(doc1);

writer.addDocument(doc2);

Sytem.out.println(writer.docCount());

writer.close();

IndexSearcher searcher = new IndexSearcher(path);

Hits hits = null;

Query query = null;

QueryParser parser =new QueryParser("name", new StandardAnalyzer());

query =parser.parse("word1");

hits = searcher.search(query);

System.out.println("查找 word1 共" + hits.length() + "个结果");

 

4.4. Directory类

Directory:用于索引的存放位置

a)         FSDirectory.getDirectory(path, true)第二个参数表示删除掉目录内原有内容

IndexWriter writer = new IndexWriter(FSDirectory.getDirectory(path, true), new StandardAnalyzer(), true);//删除原有索引

FSDirectory fsDir=FSDirectory.getDirectory(path,true);

IndexWriter writer = new IndexWriter(fsDir, new StandardAnalyzer(), true);

b)        RAMDirectory在内存中存放,读取速度快,但程序一运行结束,它的内容就不存在了

RAMDirectory ramDir=new RAMDirectory();

IndexWriter writer = new IndexWriter(ramDir, new StandardAnalyzer(), true);

 

IndexWriter writer = new IndexWriter(new RAMDirectory(), new StandardAnalyzer(), true);

4.5. IndexReader类

IndexReader类――索引的读取工具

4.5.1.删除文档

IndexReader reader=IndexReader.open(path);

reader.deleteDocument(0);//删除第一个

reader.close();

4.5.2.反删除

reader.undeleteAll();

4.5.3.按字段删除

reader.deleteDocuments(new Term("name","word1"));

若要真正物理删除,则只需使用IndexWriter对索引optimize一次即可!

4.5.4.示例

IndexReader reader=IndexReader.open(path);

           for(int i=0;i<reader.numDocs();i++){

              System.out.println(reader.document(i));

           }

           System.out.println("版本:"+reader.getVersion());

           System.out.println("索引内的文档数量:"+reader.numDocs());

           //reader.deleteDocuments(new Term("name","word1"));

           Term term1=new Term("name","word1");

           TermDocs docs=reader.termDocs(term1);

           while(docs.next())

           {

              System.out.println("含有所查找的"+term1+"的Document的编号为"+docs.doc());

              System.out.println("Term在文档中的出现次数"+docs.freq());

           }

           reader.close();

 

4.6. IndexModifier类

集成了IndexWriter的大部分功能和IndexReader中对索引删除的功能 ------ Lucene2.0的新类

 

4.6.1.示例

public static void main(String[] args) throws Exception {

       IndexModifier modifier=new IndexModifier("C:\\Q1",new StandardAnalyzer(),true);

       Document doc1=new Document();

       doc1.add(new Field("bookname","钢铁是怎样炼成的",Field.Store.YES,Field.Index.TOKENIZED));

       Document doc2=new Document();

       doc2.add(new Field("bookname","山山水水",Field.Store.YES,Field.Index.TOKENIZED));

       modifier.addDocument(doc1);

       modifier.addDocument(doc2);

      

       System.out.println(modifier.docCount());

       modifier.setUseCompoundFile(false);

       modifier.close();

      

       IndexModifier mo=new IndexModifier("C:\\Q1",new StandardAnalyzer(),false);

       mo.deleteDocument(0);

       System.out.println(mo.docCount());

       mo.close();

    }

 

4.7. IndexSearcher类

4.7.1.构造方法

IndexSearcher searcher = new IndexSearcher(String path);

IndexSearcher searcher = new IndexSearcher(Directory directory);

IndexSearcher searcher = new IndexSearcher(IndexReader r);

IndexSearcher searcher = new IndexSearcher(IndexReader r,Boolean closeReader);

IndexSearcher searcher = new IndexSearcher(path);

IndexSearcher searcher = new IndexSearcher(FSDirectory.getDirectory(path,false) );

4.7.2.search方法

//返回Hits对象

public Hits search(Query query)

public Hits search(Query query,Filter filter)

public Hits search(Query query,Sort sort)

public Hits search(Query query,Filter filter,Sort sort)

 

//检索只返回得分最高的Document

public TopDocs search(Query query,Filter filter,int n)

public TopDocs search(Weight weight,Filter filter,int n)

public TopFieldDocs search(Weight weight,Filter filter,int n,Sort sort)

public TopFieldDocs search(Query query,Filter filter,int n,Sort sort)

 

//传入HitCollector,将结果保存在HitCollector中

public void search(Query query,HitCollector results)

public void search(Query query,Filter filter,HitCollector results)

public void search(Weight weight,Filter filter,HitCollector results)

4.7.3.Searcher的explain方法

public Explaination explain(Query query,int doc)throws IOException

for(int i=0;i<hits.length()&&i<10;i++)

{

    Document d=hits.doc(i);

    System.out.println(i+" "+hits.score(i)+" "+d.get("contents"));

System.out.println(searcher.explain(query,hits.id(i)).toString());

}

4.7.4.示例

IndexSearcher searcher = new IndexSearcher(path);

Hits hits = null;

Query query = null;

 

QueryParser parser =new QueryParser("contents", new StandardAnalyzer());

 

query =parser.parse("11");

hits = searcher.search(query);

System.out.println("查找 word1 共" + hits.length() + "个结果");

 

for(int i=0;i<hits.length()&&i<10;i++)

{

    Document d=hits.doc(i);

    System.out.println(d+" "+i+" "+hits.score(i)+" "+d.get("contents"));

}

searcher.close();

4.8. Hits类

4.8.1.概述

Hits类――检索结果

4.8.2.常用方法

 

 

方法名

描述

int length()

返回搜索到结果的总数量

Document doc(int i)

返回第i个文档

int id(int i)

返回第i个文档的内部ID

float score(int i)

返回第i个文档的得分

Iterator iterator()

取得Hits集合的遍历对象

4.8.3.示例

for(int i=0;i<hits.length()&&i<10;i++)

{

    Document d=hits.doc(i);

    System.out.println(d+" "+" "+hits.score(i)+" "+d.get("contents"));

System.out.println("文档的内部ID号:" + hits.id(i));

}

4.9. QueryParser类

4.9.1.改变默认的布尔逻辑

Ø  默认为“或”关系

Query query = null;

QueryParser parser =new QueryParser("contents", new StandardAnalyzer());

query =parser.parse("hello world!");

System.out.println(query.toString());

Ø  改变默认布尔逻辑

Query query = null;

QueryParser parser =new QueryParser("contents", new StandardAnalyzer());

parser.setDefaultOperator(QueryParser.AND_OPERATOR);

query =parser.parse("hello world");//若world后加!会出错

System.out.println(query.toString());

Ø  AND OR NOT – 关键字

也可以不用改变默认布尔逻辑,而直接让用户在输入关键字时指定不同词条间的布尔联系。例如,用户输入 hello AND world  必须为大写

逻辑与:AND (大写)

逻辑或:OR  (大写)

逻辑非:-   例如: hello - world

也可以是NOT  例如: hello NOT world

4.9.2.不需要分词

不进行分词,将其完整的作为一个词条进行处理,则需要在词组的外面加上引号

String queryStr="\"God helps those who help themselves\"";

QueryParser parser = new QueryParser("bookname",new StandardAnalyzer());

parser.setDefaultOperator(QueryParser.AND_OPERATOR);

Query query=parser.parse(queryStr);

System.out.println(query.toString());

4.9.3.设置坡度值,支持FuzzyQuery

String queryStr="\"God helps those who help themselves\"~1";//设置坡度为1

QueryParser parser = new QueryParser("bookname",new StandardAnalyzer());

Query query=parser.parse(queryStr);

System.out.println(query.toString());

4.9.4.设置通配符,支持WildcardQuery

String queryStr="wor?"

QueryParser parser = new QueryParser("bookname",new StandardAnalyzer());

parser.setDefaultOperator(QueryParser.AND_OPERATOR);

Query query=parser.parse(queryStr);

System.out.println(query.toString());

4.9.5.查找指定的Field

String queryStr="linux publishdate:2006-09-01";

QueryParser parser = new QueryParser("bookname",new StandardAnalyzer());

parser.setDefaultOperator(QueryParser.AND_OPERATOR);

Query query=parser.parse(queryStr);

System.out.println(query.toString());

例如:要求用户选择某一方面的

QueryParser parser=new QueryParser("publishdate",

new StandardAnalyzer());

Query query=parser.parse(queryStr);

System.out.println(query.toString());

 

输出结果为publishdate:[081xmghs0 TO 0boeetj3z]

因为建立索引时,如果按照日期表示的字符串来进行索引,实际上比较的是字符串的字典顺序。而首先将日期转为以毫秒计算的时间后,则可以精确地比较两个日期的大小了。于是,lucene提供DateTools工具,用来完成其内部对时间的转化和处理,将毫秒级的时间转化为一个长字符串来进行表示,并进行索引。所以,遇到日期型数据时,最好用DateTools进行转换,再进行索引!

4.9.7.现在还不支持SpanQuery

4.10.        MultiFieldQueryParser类--多域搜索

//在不同的Field上进行不同的查找

public static Query parse(String []queries,String[] fields,Analyzer analyzer)throws ParseException

 

//在不同的Field上进行同一个查找,指定它们之间的布尔关系

public static Query parse(String query,String[] fields,BooleanClause.Occur[] flags,Analyzer analyzer) throws ParseException

 

//在不同的Field上进行不同的查找,指定它们之间的布尔关系

public static Query parse(String []queries,String [] fields,BooleanClause.Occur[] flags,Analyzer analyzer)throws ParseException

String [] queries={"钢", "[10 TO 20]"};

String[] fields={“bookname”,”price”};

BooleanClause.Occur[] clauses={BooleanClause.Occur.MUST,BooleanClause.Occur.MUST};

Query query=MultiFieldQueryParser.parse(queries,fields,clauses,new StandardAnalyzer());

System.out.println(query.toString());

 

4.11.        MultiSearcher类--多个索引搜索

IndexSearcher searcher1=new IndexSearcher(path1);

IndexSearcher searcher2=new IndexSearcher(path2);

IndexSeacher [] searchers={searcher1,seacher2};

MultiSearcher searcher=new MultiSearcher(searchers);

Hits hits=searcher.search(query);

for(int i=0;i<hits.length();i++){

    System.out.println(hits.doc(i));

}

4.12.        ParalellMultiSearcher类---多线程搜索

IndexSearcher searcher1=new IndexSearcher(path1);

IndexSearcher searcher2=new IndexSearcher(path2);

IndexSearcher [] searchers={searcher1,searcher2};

ParallelMultiSearcher searcher=new ParallelMultiSearcher(searchers);

long start=System.currentTimeMillis();

Hits hits=searcher.search(query);

long end=System.currentTimeMillis();

System.out.println((end-start)+"ms");

5.    排序

5.1. Sort类

public Sort()

public Sort(String field)

public Sort(String field,Boolean reverse)  //默认为false,降序排序

public Sort(String[] fields)

public Sort(SortField field)

public Sort(SortField[] fields)

Sort sort=new Sort(“bookname”);按照“bookname“这个Field值进行降序排序

Sort sort=new Sort(“bookname”,true) //升序排序

Sort sort=new Sort(new String[]{“bookNumber”,”bookname”,”publishdate”});按照三个Field进行排序,但无法指定升序排序,所以用SortField

5.2. SortField类

public SortField(String field)

public SortField(String field,Boolean reverse)

public SortField(String field,int type) //type表示当前Field值的类型

public SortField(String field,int type,boolean reverse)  //默认为false,升序

Field值的类型:SortField.STRING、SortField.INT、SortField.FLOAT

SortField sf1=new SortField(“bookNumber”,SortField.INT,false);

SortField sf2=new SortField(“bookname”,SortField.STRING,false);

5.3. 指定排序的法则

5.3.1.按照文档的得分降序排序

Hits hits=searcher.search(query,Sort.RELEVANCE);

5.3.2.按文档的内部ID升序排序

Hits hits=searcher.search(query, Sort.INDEXORDER);

5.3.3.按照一个Field来排序

Sort sort=new Sort();

SortField sf=new SortField(“bookNumber”,SortField.INT,false);

sort.setSort(sf);

Hits hits=searcher.search(query,sort);

5.3.4.按照多个Field来排序

Sort sort=new Sort();

SortField sf1=new SortField(“bookNumber”,SortField.INT,false);//升序

SortField sf2=new SortField(“publishdate”,SortField.STRING,true);//降序

sort.setSort(new SortField[]{sf1,sf2});

Hits hits=searcher.search(query,sort);

5.3.5.改变SortField中的Locale信息

String str1=”我”; String str2=”你”;

Collator co1=Collator.getInstance(Locale.CHINA);

Collator co2=Collator.getInstance(Locale.JAPAN);

System.out.println(Locale.CHINA+”:”+co1.compare(str1,str2));

System.out.println(Locale.JAPAN+”:”+co2.compare(str1,str2));

输出结果为:

zh_CN:1

ja_JP:-1

所以

public SortField(String field,Locale locale)

public SortField(String field,Locale locale,boolean reverse)

6.    过滤器

使用public Hits search(Query query,Filter filter)

(1)简单过滤

Hits hits=searcher.search(query,new AdvancedSecurityFilter());//过滤掉securitylevel为0的结果

(2)范围过滤—RangeFilter

只显示中间的

RangeFilter filter=new RangeFilter(“publishdate”,”1970-01-01”,”1998-12-31”,true,true”);

Hits hits=searcher.search(query,filter);

 

无上边界

public static RangeFilter More(String fieldname,String lowerTerm)

 

无下边界

public static RangeFilter Less(String fieldname,String upperTerm)

(3)在结果中查询QueryFilter

RangeQuery q=new RangeQuery(new Term(“publicshdate”,”1970-01-01”),

new Term(“publishdate”,”1999-01-01”),true);

QueryFilter filter=new QueryFilter(q);

Hits hits=searcher.search(query,filter);

7.    分析器Analysis

7.1. 自带分析器和过滤器

Ø  标准过滤器:StandardAnalyzer

Ø  大小写转换器:LowerCaseFilter

Ø  忽略词过滤器:StopFilter

public StopFilter(TokenStream input,String [] stopWords)

public StopFilter(TokenStream in,String [] stopWords,boolean ignoreCase)

public StopFilter(TokenStream input,Set stopWords,boolean ignoreCase)

public StopFilter(TokenStream in, Set stopWords)

其中,参数TokenStream代表当前正在进行处理的流;String类型的数组代表一个用数组表示的忽略词集合;Set类型的参数与String一样,是用来表示忽略词集合的;boolean表示当与忽略词集合中的词进行匹配时,是否需要忽略大小写。

Ø  长度过滤器:LengthFilter

Ø  PerFieldAnalyzerWrapper

Ø  WhitespaceAnalyzer

String str="str1 str2 str3";

       StringReader reader=new StringReader(str);

       Analyzer anlyzer=new WhitespaceAnalyzer();

      

       TokenStream ts=anlyzer.tokenStream("", reader);

       Token t=null;

       while( (t=ts.next())!=null ){

           System.out.println(t.termText());

       }

7.2. 第三方过分析器

Ø  单字分词

Ø  二分法:CJKAnalyzer、中科院ICTCLAS分词、JE分词

Ø  词典分词

7.2.1.JE分词用法

7.2.1.1.   示例

import jeasy.analysis.MMAnalyzer;

IndexWriter writer = new IndexWriter(INDEX_STORE_PATH, new MMAnalyzer()

, true);

String str=" Lucene是一个全文检索引擎的架构,"+

           "提供了完整的查询引擎和索引引擎。Lucene以其方便使用、快" +

           "速实施以及灵活性受到广泛的关注。它可以方便地嵌入到各种应用" +

           "中实现针对应用的全文索引、检索功能,本总结使用lucene--2.3.2。";

       MMAnalyzer analyzer=new MMAnalyzer();

       try{

           System.out.println(analyzer.segment(str, "|"));

       }

       catch(Exception e)

       {

           e.printStackTrace();

       }

输出结果:lucene|一个|全文|检索|引擎|架构|提供|完整|查询|。。。。

7.2.1.2.   设定正向最大匹配的字数

MMAnalyzer analyzer=new MMAnalyzer(4);

7.2.1.3.   添加新词

MMAnalyzer.addWord(String word);

MMAnalyzer.addDictionary(Reader reader);

 

MMAnalyzer analyzer=new MMAnalyzer();

MMAnalyzer.addWord("迈克尔雷第");

 

8.    索引的合并

RAMDirectory RAMDir=new RAMDirectory();

IndexWriter writer = new IndexWriter(RAMDir, new StandardAnalyzer(), true);//删除原有索引

IndexWriter writer2=new IndexWriter(FSDirectory.getDirectory(path,true),

new StandardAnalyzer(), true);

writer.addDocument(doc1);

writer2.addDocument(doc2);

writer.close();

writer2.addIndexes(new Directory[]{RAMDir});

writer2.close();

注意:在合并前一定要先关闭要加的索引器。

9.    各种Query

9.1. 概述

query.toString()查看原子查询

9.2. 使用特定的分析器搜索

IndexSearcher searcher = new IndexSearcher(path );

Hits hits = null;

Query query = null;

QueryParser parser =new QueryParser("contents", new StandardAnalyzer());

query =parser.parse("11 aand hello");

hits=searcher.search(query); //查找 name:11 name:hello 共1个结果

System.out.println("查找 "+query.toString()+" 共" + hits.length() + "个结果");

9.3. 按词条搜索—TermQuery

Query query = null;

query=new TermQuery(new Term("name","word1 aand"));

hits=searcher.search(query);// 查找 name:word1 aand 共0个结果

System.out.println("查找 "+query.toString()+" 共" + hits.length() + "个结果");

9.4. 按“与或”搜索—BooleanQuery

1.和: MUST与MUST_NOT

2.或: SHOULD与SHOULD

3.A与B的并集-B  MUST与MUST_NOT

Query query1=null;

Query query2=null;

BooleanQuery query=null;

query1=new TermQuery(new Term("name","word1"));

query2=new TermQuery(new Term("name","word2"));

query=new BooleanQuery();

query.add(query1,BooleanClause.Occur.MUST);

query.add(query2,BooleanClause.Occur.MUST_NOT);

9.5. 在某一范围内搜索—RangeQuery

Term beginTime=new Term("time","200001");

Term endTime=new Term("time","200005");

RangeQuery query=null;

query=new RangeQuery(beginTime,endTime,false);//不包含边界值

9.6. 使用前缀搜索—PrefixQuery

Term pre1=new Term("name","wor");

PrefixQuery query=null;

query = new PrefixQuery(pre1);

9.7. 短语搜索—PhraseQuery

a)默认坡度为0

PhraseQuery query = new PhraseQuery();

query.add(new Term(“bookname”,”钢”));

query.add(new Term(“bookname”,”铁”));

Hits hits=searcher.search(query); //搜索“钢铁”短语,而非“钢”和“铁”

b)设置坡度,默认为0

PhraseQuery query = new PhraseQuery();

query.add(new Term(“bookname”,”钢”));

query.add(new Term(“bookname”,”铁”));

query.setSlop(1);

Hits hits=searcher.search(query);//搜索“钢铁”或“钢*铁”中含一字

9.8. 多短语搜索—MultiPhraseQuery

a)

MultiPhraseQuery query=new MultiPhraseQuery();

//首先向其中加入要查找的短语的前缀

query.add(new Term(“bookname”,”钢”));

//构建3个Term,作为短语的后缀

Term t1=new Term(“bookname”,”铁”);

Term t2=new Term(“bookname”,”和”);

Term t3=new Term(“bookname”,”要”);

//再向query中加入所有的后缀,与前缀一起,它们将组成3个短语

query.add(new Term[]{t1,t2,t3});

Hits hits=searcher.search(query);

for(int i=0;i<hits.length();i++)

    System.out.println(hits.doc(i));

b)

MultiPhraseQuery query=new MultiPhraseQuery();

Term t1=new Term(“bookname”,”钢”);

Term t2 = new Term(“bookname”,”和”);

query.add(new Term[]{t1,t2});

query.add(new Term(“bookname”,”铁”));

c)

MultiPhraseQuery query=new MultiPhraseQuery();

Term t1=new Term(“bookname”,”钢”);

Term t2 = new Term(“bookname”,”和”);

query.add(new Term[]{t1,t2});

query.add(new Term(“bookname”,”铁”));

Term t3=new Term(“bookname”,”是”);

Term t4=new Term(“bookname”,”战”);

query.add(new Term[]{t3,t4});

9.9. 模糊搜索—FuzzyQuery

使用的算法为levenshtein算法,在比较两个字符串时,将动作分为3种:

l  加一个字母

l  删一个字母

l  改变一个字母

FuzzyQuery query=new FuzzyQuery(new Term(“content”,”work”));

 

public FuzzyQuery(Term term)

public FuzzyQuery(Term term,float minimumSimilarity)throws IllegalArgumentException

public FuzzyQuery(Term term,float minimumSimilarity,int prefixLength)throws IllegalArgumentException

其中minimumSimilarity为最小相似度,越小则文档的数量越多。默认为0.5.其值必须<1.0

FuzzyQuery query=new FuzzyQuery(new Term(“content”,”work”),0.1f);

其中prefixLength表示要有多少个前缀字母必须完全匹配

FuzzyQuery query=new FuzzyQuery(new Term(“content”,”work”),0.1f,1);

9.10.        通配符搜索—WildcardQuery

* 表示0到多个字符

? 表示一个单一的字符

WildcardQuery query=new WildcardQuery(new Term(“content”,”?qq*”));

9.11.        跨度搜索

9.11.1.      SpanTermQuery

效果和TermQuery相同

SpanTermQuery query=new SpanTermQuery(new Term(“content”,”abc”));

9.11.2.      SpanFirstQuery

从Field内容的起始位置开始,在一个固定的宽度内查找所指定的词条

SpanFirstQuery query=new SpanFirstQuery(new Term(“content”,”abc”),3);//是第3个word,不是byte

9.11.3.      SpanNearQuery

SpanNearQuery相当与PhaseQuery

SpanTermQuery people=new SpanTermQuery(new Term(“content”,”mary”));

SpanTermQuery how=new SpanTermQuery(new Term(“content”,”poor”));

SpanNearQuery query=new SpanNearQuery(new SpanQuery[]{people,how},3,false);

9.11.4.      SpanOrQuery

把所有SpanQuery的结果合起来

SpanTermQuery s1=new SpanTermQuery(new Term(“content”,”aa”);

SpanTermQuery s2=new SpanTermQuery(new Term(“content”,”cc”);

SpanTermQuery s3=new SpanTermQuery(new Term(“content”,”gg”);

SpanTermQuery s4=new SpanTermQuery(new Term(“content”,”kk”);

SpanNearQuery query1=new SpanNearQuery(new SpanQuery[]{s1,s2},1,false);

SpanNearQuery query2=new SpanNearQuery(new SpanQuery[]{s3,s4},3,false);

SpanOrQuery query=new SpanOrQuery(new SpanQuery[]{query1,query2});

9.11.5.      SpanNotQuery

从第1个SpanQuery的查询结果中,去掉第2个SpanQuery的查询结果

SpanTermQuery s1=new SpanTermQuery(new Term(“content”,”aa”);

SpanFirstQuery query1=new SpanFirstQuery(s1,3);

 

SpanTermQuery s3=new SpanTermQuery(new Term(“content”,”gg”);

SpanTermQuery s4=new SpanTermQuery(new Term(“content”,”kk”);

SpanNearQuery query2=new SpanNearQuery(new SpanQuery[]{s3,s4},4,false);

 

SpanNotQuery query=new SpanNotQuery(query1,query2);

9.12.        RegexQuery—正则表达式的查询

String regex="http://[a-z]{1,3}\\.abc\\.com/.*";

       RegexQuery query=new RegexQuery(new Term("url",regex));

 

10.   评分机制

10.1.        概述

通过searcher.explain(Query query, int doc)方法可以查看某个文档的得分的具体构成。

在Lucene中score简单说是由 tf * idf * boost * lengthNorm计算得出的。

1)        tf:Term Frequency.词条频率,是查询的词在文档中出现的次数的平方根

2)        idf:表示反转文档频率,Math.log(numDocs/(double)(docFreq+1))+1.0   docDocs表示当前检索的词条的文档总数, numDocs表示索引中总共的文档数量

3)        boost:激励因子,可以通过setBoost方法设置,需要说明的通过field和doc都可以设置,所设置的值会同时起作用 。默认为1.boost的值是在索引建立的时候已经写入了,而不像其他计算得分的因子是在查询时实时得出的。因此,一旦boost值被写入,就不能修改它,除非重新建立文档索引。

4)        lengthNorm:是由搜索的field的长度决定了,越长文档的分值越低。

11.   Lucene的索引“锁”

1.    write.lock

2.    commit.lock

 

转载于:https://my.oschina.net/lujian863/blog/152018

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/265726.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安卓APP开发基础

目录安卓工程构建第一个APP运行安卓的工程目录文件夹介绍安卓APP启动过程安卓布局控件布局的种类布局和页面的关系显示一张美女图显示两个美女常用布局之相对布局基础控件之Button,TextView,EditText,ImageView, padding和margin(内外边框)相对布局综合小演练-智能家居刷卡界面…

jquery.ui.draggable中文文档jquery 自由拖拽类~study~

为什么80%的码农都做不了架构师&#xff1f;>>> JQuery UI Draggable插件用来使选中的元素可以通过鼠标拖动. Draggable的元素受影响css: ui-draggable, 拖动过程中的css: ui-draggable-dragging. 如果需要的不仅仅是拖, 而是一个完整的拖放功能, 请参阅JQue…

数据结构——二叉树先序、中序、后序及层次四种遍历(C语言版)

摘自&#xff1a;数据结构——二叉树先序、中序、后序及层次四种遍历&#xff08;C语言版&#xff09; 作者&#xff1a;正弦定理 发布时间&#xff1a;2020-12-09 17:08:48 网址&#xff1a;https://blog.csdn.net/chinesekobe/article/details/110874773?ops_request_misc%2…

js 获取td高度_JS或jQuery获取宽高度

javascript//网页可见区域宽&#xff1a; document.body.clientWidth //网页可见区域高&#xff1a; document.body.clientHeight //网页可见区域宽&#xff1a; document.body.offsetWidth (包括边线的宽) //网页可见区域高&#xff1a; document.body.offsetHeight (包括…

一些比较少用但比较有用的linux命令备忘

网络相关 ssh 反向代理 ssh -fCNR 10000:localhost:22 userBB.B.B.B B.B.B.B是一个外网机器B的IP ssh -p 10000 userAlocalhost 在机器B&#xff0c;ssh到机器A 防火墙 查看防火墙服务状态 systemctl status firewalld查询端口是否开放 firewall-cmd --query-port8080/tcp…

安卓网络编程(Socket、WebView控件)

目录JavaSocket服务端开发JavaSocket客户端开发安卓Socket客户端开发接收消息显示到控件上(解决安卓线程无法修改控件问题)Android网络接收数据并刷新界面显示安卓webView智能家居你APP页面开发JavaSocket服务端开发 import java.io.IOException; import java.io.InputStream; …

(转)iOS Wow体验 - 第五章 - 利用iOS技术特性打造最佳体验

本文是《iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad》第五章译文精选&#xff0c;其余章节将陆续放出。上一篇&#xff1a;Wow体验 - 第四章 - 为应用的上下文环境而设计 关于本套译文分享的详情及目录结构&#xff0c;请参考iOS Wow体验 - 译文分享说…

fetch 自动加cookie_WEBUI自动化开发(第五章)

Requests是Python的非常常用的HTTP的库&#xff0c;主要用于网络爬虫和接口自动化测试。下面使用Requests最新版本&#xff0c;通过pip install requests安装。pip install requestsCollecting requests Downloading requests-2.25.0-py2.py3-none-any.whl (61 kB) |███…

结构体对齐计算方式

目录法则一&#xff1a;结构体成员的偏移量必须是成员大小的整数倍(数组除外)法则二&#xff1a;结构体大小必须是所有成员大小的整数倍(数组、结构体除外)带数组的结构体大小计算带结构体的结构体大小计算带联合体的结构体大小计算pragma pack(4)向4对齐对齐方式确实很浪费空间…

【计算机算法设计与分析】——5.4最优二分检索树

&#xff08;n为结点个数&#xff09; 为成本差额 转载于:https://www.cnblogs.com/chihaoyuIsnotHere/p/9815498.html

dataframe常用操作_Pandas | Dataframe的merge操作,像数据库一样尽情join

点击上方蓝字&#xff0c;关注并星标&#xff0c;和我一起学技术。今天是pandas数据处理第8篇文章&#xff0c;我们一起来聊聊dataframe的合并。常见的数据合并操作主要有两种&#xff0c;第一种是我们新生成了新的特征&#xff0c;想要把它和旧的特征合并在一起。第二种是我们…

2.空间配置器

SGI 特殊的空间配置器 std::alloc 一般而言&#xff0c;我们习惯的C内存配置操作和释放操作是这样的 class Foo{…..} Foo* pf new Foo; delete pf; new包含两阶段操作 &#xff08;1&#xff09;调用 ::operator new 配置内存 &#xff08;2&#xff09;调用 Foo::Foo() …

Github的简单使用(网页版)

目录Git和GithubGithub基础概念注册Github账号创建仓库及文件新建仓库新建文件文件的编辑和删除编辑或修改文件删除文件文件的上传文件的查找及下载文件的查找文件的下载IssuesFork开源项目贡献流程Git和Github 什么是Git Git是一个免费、开源的版本控制软件 什么是版本控制…

常用到的正则表达式

2019独角兽企业重金招聘Python工程师标准>>> 常用的正则表达式 1、匹配只含有英文字母和阿拉伯数字 ^[a-zA-Z0-9-]$ 2、匹配电子邮件地址 ^[_a-z0-9-](\.[_a-z0-9-])*[a-z0-9-](\.[a-z0-9-])*$ 3、匹配中文字符 [\u4e00-\u9fa5] 4、匹配国内座机电话号码 (\d{3}-|\d…

CSDN绑定GitHub账号

目录1.点击自己头像进入个人中心2.点击账号设置&#xff0c;选择绑定三方账号3.选择GitHub绑定绑定成功&#xff0c;主页获取勋章1.点击自己头像进入个人中心 2.点击账号设置&#xff0c;选择绑定三方账号 3.选择GitHub绑定 绑定成功&#xff0c;主页获取勋章

My97DatePicker在asp.net项目中的使用

1、去官网下载 My97DatePicker 包 http://www.my97.net/ 2、比如实现如下图所示功能 2.1 先把下载来的包添加到解决方案 2.2 然后在页面引用css文件和js文件 <link href"My97DatePicker/skin/WdatePicker.css" rel"stylesheet" type"text/css"…

机械秒表的使用方法_让console.log()不再是你的唯一选项js日志输出6种方法

几乎所有的javascript开发者最常使用的日志打印调试api都是console.log(),其实还有很多的选项供我们选择&#xff0c;笔者下面就为大家一一介绍.一、console.table()console.table()是我非常建议大家去使用的方法&#xff0c;它可以接受JSON或数组并以表格格式打印&#xff0c;…

Git的安装(附安装包)

更多干货推荐可以去牛客网看看&#xff0c;他们现在的IT题库内容很丰富&#xff0c;属于国内做的很好的了&#xff0c;而且是课程刷题面经求职讨论区分享&#xff0c;一站式求职学习网站&#xff0c;最最最重要的里面的资源全部免费&#xff01;&#xff01;&#xff01;点击进…

【10.20校内测试】【小模拟】【无向图建树判奇偶环】【树上差分】

Solution 和后面两道题难度差距太大了吧&#xff01;&#xff01; 显然就只是个小模拟&#xff0c;注意判0就行了。 Code #include<bits/stdc.h> using namespace std;char s[100005];int main() {freopen("expression.in", "r", stdin);freopen(&qu…

微信(QQ)截图时,无法保留鼠标右键菜单选项内容

问题描述 按下右键后弹出菜单&#xff0c;再按下QQ截图热键"Ctrl&#xff0b;Alt&#xff0b;A"&#xff08;微信"Ctrl&#xff0b;A"&#xff09;时&#xff0c;却发现菜单不见了。 微信的解决方法 先按下"Alt"键不放&#xff0c;再按住&quo…