java 多关联字联合搜索_【lucene】高级搜索篇

本文深入探讨了Lucene的排序机制,包括Query类、Weight接口、Scorer类和Similarity类的角色。讲解了如何利用Sort对象进行相关性、文档编号、独立域、联合域和逆向排序,并提供了示例代码展示如何实现这些排序策略。通过设置文档和字段的Boost值,可以调整搜索结果的排序,实现多关联字联合搜索的高级功能。
摘要由CSDN通过智能技术生成

一,概念

1、 Lucene相关排序流程

找到关键词匹配的文档集合---->文档集合每个文档计算检索相似度----->对文档集合进行排序

2、 Lucene相关类

① Query类:一个抽象类, Lucene检索结果最终评分的总控制中心。其它评分有关的类和对象都是由 Query类来管理和生产。

② Weight类接口:定义 Query权重计算的一个实现接口,可以被重用。 Weight类可以用来生成 Scorer类,也可以解析评分的详细信息,另外还定义了获取 Query权值的方法。

③ Scorer类: Lucene评分机制的核心类。类的定义是抽象类,提供的一些抽象基本的计分功能方法提供所有的评分类实现,同时还定义了评分的详细解析方法, Scorer类内部有一个 Similarity对象,用来指明计算公式。

④ Scorer类: Lucene相似度计算的核心抽象类。 Similarity类主要处理评分计算,系统缺省使用类 DefaultSimilarity类对象

3、 排序控制

使用 Sort对象定制排序,通过改变文档 Boost值来改变排序结果以及使用自定义的 Similarity方法更改排序

4、 文档 Boost加权排序

① Boost是指索引建立过程中,给整篇文档或者文档的某一特定域设定的权值因子,在检索时,优先返回分数高的。

Document和 Field两重 Boosting参数。通过 Document对象的 setBoost()方法和 Field对象的 setBoost()方法。不同在于前者对文档中每一个域都修改了参数,而后者只针对指定域进行修改。

文档加权 =Document-boosting*Field-boosting,默认情况下为 1,一般不做修改。

② Sort对象检索排序

Sort使用时通过实例化对象作为参数,通过 Searcher类的 search接口来实现。 Sort支持的排序功能以文档当中的域为单位,通过这种方法,可以实现一个或者多个不同域的多形式的值排序。

实际使用排序对象 Sort进行排序。主要有两种模式,一种是以字符串表示文档域的名称作为参数指定域排序,一种是直接以排序域的包装域的包装类作为参数进行排序。

Sort对象使用比较简单,只需要在对文档索引进行检索时,在检索器的 Search方法中带 Sort对象作为参数即可。

1) Sort对象相关性排序

按照相关性排序时最基本的结果排序方法,使用 Sort对象无参数构造函数完成的排序效果相当于 Lucene默认的按相关性降序排序。

2) Sort对象文档编号排序

某些应用场合需要对所有符合匹配度的结果,按照文档内部编号排序输出。使用 Sort对象的静态实例 Sort.INDEXORDER来实现

3) Sort对象独立域排序

在检索过程中,把检索结果按照某一个特定域排序,非常重要。在使用搜索引擎过程中,有时会选择使用时间排序,而在搜索引擎库中,检索词完全是另外一个域的内容,与时间没有任何关系。这种应用中,检索关键词的匹配仍然是首要因素,匹配太低或者不匹配的文档直接不必处理,而匹配的文档则需进一步排序输出。

指定的排序域并没有进行特别限制,可以是检索词的关联域,也可以是文档中的任意其它域。

4) Sort对象联合域排序

多个文档域联合排序时,需要注意文档域的添加次序。排序的结果先按照第一个域排序,然后第二个域作为次要关键字排序。开发时,需要根据自己的需要选择合适的次序。

5) Sort对象逆向排序

Sort(field,true)或者 Sort(field,false)实现升降序排序。

二,例子

/*

* To change this template, choose Tools | Templates

* and open the template in the editor.

*/

package sorttest;

import java.io.File;

import org.apache.lucene.analysis.standard.StandardAnalyzer;

import org.apache.lucene.document.Document;

import org.apache.lucene.document.Field;

import org.apache.lucene.index.IndexWriter;

import org.apache.lucene.index.Term;

import org.apache.lucene.index.IndexWriter.MaxFieldLength;

import org.apache.lucene.search.IndexSearcher;

import org.apache.lucene.search.ScoreDoc;

import org.apache.lucene.search.Sort;

import org.apache.lucene.search.TermQuery;

import org.apache.lucene.store.Directory;

import org.apache.lucene.store.FSDirectory;

import org.apache.lucene.util.Version;

public class SortTest {

public static void makeItem(IndexWriter writer, String bookNumber,

String bookName, String publishDate) throws Exception {

writer.setUseCompoundFile(false);

Document doc = new Document();

Field f1 = new Field("bookNumber", bookNumber, Field.Store.YES,

Field.Index.NOT_ANALYZED);

Field f2 = new Field("bookName", bookName, Field.Store.YES,

Field.Index.ANALYZED);

Field f3 = new Field("publishDate", publishDate, Field.Store.YES,

Field.Index.NOT_ANALYZED);

doc.add(f1);

doc.add(f2);

doc.add(f3);

writer.addDocument(doc);

}

public static void main(String[] args) {

String Index_Store_Path = "D:\\luceneIndex";

File file = new File(Index_Store_Path);

try {

Directory Index = FSDirectory.open(file);

IndexWriter writer = new IndexWriter(Index, new StandardAnalyzer(Version.LUCENE_CURRENT), true,MaxFieldLength.LIMITED);

writer.setUseCompoundFile(false);

Document doc1 = new Document();

Field f11 = new Field("bookNumber", "0000001", Field.Store.YES, Field.Index.NOT_ANALYZED);

Field f12 = new Field("bookName", " 钢铁是怎样炼成的 ", Field.Store.YES, Field.Index.ANALYZED);

Field f13 = new Field("publishDate", "1970-01-01", Field.Store.YES, Field.Index.NOT_ANALYZED);

doc1.add(f11);

doc1.add(f12);

doc1.add(f13);

Document doc2 = new Document();

Field f21 = new Field("bookNumber", "0000002", Field.Store.YES, Field.Index.NOT_ANALYZED);

Field f22 = new Field("bookName", " 钢铁战士 ", Field.Store.YES, Field.Index.ANALYZED);

Field f23 = new Field("publishDate", "1970-01-01", Field.Store.YES, Field.Index.NOT_ANALYZED);

doc2.add(f21);

doc2.add(f22);

doc2.add(f23);

Document doc3 = new Document();

Field f31 = new Field("bookNumber", "0000003", Field.Store.YES, Field.Index.NOT_ANALYZED);

Field f32 = new Field("bookName", " 篱笆女人和狗 ", Field.Store.YES, Field.Index.ANALYZED);

Field f33 = new Field("publishDate", "1970-01-01", Field.Store.YES, Field.Index.NOT_ANALYZED);

doc3.add(f31);

doc3.add(f32);

doc3.add(f33);

Document doc4 = new Document();

Field f41 = new Field("bookNumber", "0000004", Field.Store.YES, Field.Index.NOT_ANALYZED);

Field f42 = new Field("bookName", " 女人是水做的 ", Field.Store.YES, Field.Index.ANALYZED);

Field f43 = new Field("publishDate", "1970-01-01", Field.Store.YES, Field.Index.NOT_ANALYZED);

doc4.add(f41);

doc4.add(f42);

doc4.add(f43);

Document doc5 = new Document();

Field f51 = new Field("bookNumber", "0000005", Field.Store.YES, Field.Index.NOT_ANALYZED);

Field f52 = new Field("bookName", " 英雄儿女 ", Field.Store.YES, Field.Index.ANALYZED);

Field f53 = new Field("publishDate", "1970-01-01", Field.Store.YES, Field.Index.NOT_ANALYZED);

doc5.add(f51);

doc5.add(f52);

doc5.add(f53);

Document doc6 = new Document();

Field f61 = new Field("bookNumber", "0000006", Field.Store.YES, Field.Index.NOT_ANALYZED);

Field f62 = new Field("bookName", " 白毛女 ", Field.Store.YES, Field.Index.ANALYZED);

Field f63 = new Field("publishDate", "1970-01-01", Field.Store.YES, Field.Index.NOT_ANALYZED);

doc6.add(f61);

doc6.add(f62);

doc6.add(f63);

Document doc7 = new Document();

Field f71 = new Field("bookNumber", "0000007", Field.Store.YES, Field.Index.NOT_ANALYZED);

Field f72 = new Field("bookName", " 我的兄弟和女儿 ", Field.Store.YES, Field.Index.ANALYZED);

Field f73 = new Field("publishDate", "1970-01-01", Field.Store.YES, Field.Index.NOT_ANALYZED);

doc7.add(f71);

doc7.add(f72);

doc7.add(f73);

writer.addDocument(doc1);

writer.addDocument(doc2);

writer.addDocument(doc3);

writer.addDocument(doc4);

writer.addDocument(doc5);

writer.addDocument(doc6);

writer.addDocument(doc7);

writer.optimize();

writer.close();

IndexSearcher searcher = new IndexSearcher(Index);

TermQuery q = new TermQuery(new Term("bookName", "女"));

//ScoreDoc[] hits = searcher.search(q, null, 1000, Sort.RELEVANCE).scoreDocs;

//ScoreDoc[] hits = searcher.search(q, null, 1000, Sort.INDEXORDER).scoreDocs;

ScoreDoc[] hits = searcher.search(q, null, 1000).scoreDocs;

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

Document hitDoc = searcher.doc(hits[i].doc);

System.out.print("书名 :");

System.out.println(hitDoc.get("bookName"));

System.out.print("得分 :");

System.out.println(hits[i].score);

System.out.print("内部 ID :");

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

System.out.print("书号 :");

System.out.println(hitDoc.get("bookNumber"));

System.out.print("发行日期 :");

System.out.println(hitDoc.get("publishDate"));

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

在代码中

//ScoreDoc[] hits = searcher.search(q, null, 1000, Sort.RELEVANCE).scoreDocs;

//ScoreDoc[] hits = searcher.search(q, null, 1000, Sort.INDEXORDER).scoreDocs;

ScoreDoc[] hits = searcher.search(q, null, 1000).scoreDocs;

根据不同的Sort 属性就会得到不同的结果。自己尝试一下吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值