`
twh1224
  • 浏览: 95600 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Lucene学习(20)

阅读更多
关于Field类和Document类。

初始化一个IndexWriter索引器之后,就可以向其中添加Document了。然而,Document逻辑文件能够与一个物理文件对应起来,在Lucene中,Document主要是维护添加到其中的多个Field。

关于Field在文章 Lucene-2.2.0 源代码阅读学习(3) 中可以了解到一点相关内容,Field类的定义比较简单,它给出了7种构造一个Field对象的构造方法:

public Field(String name, byte[] value, Store store) 
public Field(String name, Reader reader) 
public Field(String name, Reader reader, TermVector termVector) 
public Field(String name, String value, Store store, Index index) 
public Field(String name, String value, Store store, Index index, TermVector termVector) 
public Field(String name, TokenStream tokenStream) 
public Field(String name, TokenStream tokenStream, TermVector termVector) 


Field类的内部定义了三个内部类,其中内部类Store和Index是非常重要的,它指定了一个Field被创建的时候,在索引、存储、分词方面进行选择,可以有不同的选择方式:

// Store是一个内部类,它是static的,主要为了设置Field的存储属性 
public static final class Store extends Parameter implements Serializable {

	private Store(String name) {
		super(name);
	}

	// 在索引中压缩存储Field的值 
	public static final Store COMPRESS = new Store("COMPRESS");

	// 在索引中存储Field的值 
	public static final Store YES = new Store("YES");

	// 在索引中不存储Field的值 
	public static final Store NO = new Store("NO");
}

//通过Index设置索引方式 
public static final class Index extends Parameter implements Serializable {

	private Index(String name) {
		super(name);
	}

	// 不对Field进行索引,所以这个Field就不能被检索到(一般来说,建立索引而使它不被检索,这是没有意义的) 
	// 如果对该Field还设置了Field.Store为Field.Store.YES或Field.Store.COMPRESS,则可以检索 
	public static final Index NO = new Index("NO");

	// 对Field进行索引,同时还要对其进行分词(由Analyzer来管理如何分词) 
	public static final Index TOKENIZED = new Index("TOKENIZED");

	// 对Field进行索引,但不对其进行分词 
	public static final Index UN_TOKENIZED = new Index("UN_TOKENIZED");

	// 对Field进行索引,但是不使用Analyzer 
	public static final Index NO_NORMS = new Index("NO_NORMS");

}


第三个内部类是TermVector类,内部类的定义如下:

// 指定一个Field是否要存储一个词条向量,以怎样的方式来存储这个词条向量 
public static final class TermVector extends Parameter implements Serializable { 
 
    private TermVector(String name) {    // 通过指定一个字符串,来构造一个Field的TermVector,指定该Field的对词条的设置方式 
      super(name); 
    } 
 
    // 不存储 
    public static final TermVector NO = new TermVector("NO"); 
    
    // 为每个Document都存储一个TermVector 
    public static final TermVector YES = new TermVector("YES"); 
    
    // 存储,同时存储位置信息 
    public static final TermVector WITH_POSITIONS = new TermVector("WITH_POSITIONS"); 
    
    // 存储,同时存储偏移量信息 
    public static final TermVector WITH_OFFSETS = new TermVector("WITH_OFFSETS"); 
    
    // 存储,同时存储位置、偏移量信息 
    public static final TermVector WITH_POSITIONS_OFFSETS = new   TermVector("WITH_POSITIONS_OFFSETS"); 
} 


另外,Field类实现了Fieldabel接口类,可以通过了解Fieldable接口的定义,来了解Field类都实现了哪些方法,这些方法的功能是什么。

Fieldable接口类的定义如下所示:

package org.apache.lucene.document;

import java.io.Reader;
import java.io.Serializable;

import org.apache.lucene.analysis.TokenStream;

public interface Fieldable extends Serializable {
	/* 设置命中该Field的boost因子,这个值将被乘到一个排序分值上,这个分值是这个Document中的该Field被命中的分值。 
	 // The boost is multiplied by {@link org.apache.lucene.document.Document#getBoost()} of the document。 
	 Document的getBoost()方法返回一个值,这个值将与boost相乘,这里要求是包含该Field的Document。如果一个Document中有多个名字相同的Field,则这些值需要乘到一起。得到的乘积结果,再乘到 {@link org.apache.lucene.search.Similarity#lengthNorm(String,int)}上,并且,在存储到索引中之前,rounded by {@link org.apache.lucene.search.Similarity#encodeNorm(float)} 要保证乘积结果没有溢出。 
	 */
	void setBoost(float boost);

	// 返回boost的值 
	float getBoost();

	/** 返回一个Field的内部字符串,例如:. 
	 * "date"、"title"、"body"等等 
	 */
	String name();

	// Field的字符串值,或null。 
	public String stringValue();

	// Field作为一个Reader的值,或null。 
	public Reader readerValue();

	// Field作为Binary的值,或null。 
	public byte[] binaryValue();

	// Field作为一个TokenStream的值,或null。 
	public TokenStream tokenStreamValue();

	// 当且仅当Field的值被存储到索引中时,返回 
	boolean isStored();

	// 当且仅当Field的被索引时,以便能够检索到,返回true 
	boolean isIndexed();

	// Field的值是否被分词 
	boolean isTokenized();

	// 是否被压缩存储 
	boolean isCompressed();

	// 词条用于索引该Field,则以词条向量的形式存储 
	boolean isTermVectorStored();

	/** 
	 * True iff terms are stored as term vector together with their offsets 
	 * (start and end positon in source text). 
	 */
	boolean isStoreOffsetWithTermVector();

	/** 
	 * True iff terms are stored as term vector together with their token positions. 
	 */
	boolean isStorePositionWithTermVector();

	// Field的值是否以二进制存储 
	boolean isBinary();

	//   该Field是否索引,但不分词 
	boolean getOmitNorms();

	/** Expert: 
	 * 
	 * If set, omit normalization factors associated with this indexed field. 
	 * This effectively disables indexing boosts and length normalization for this field. 
	 */
	void setOmitNorms(boolean omitNorms);

	// 是否延迟加载,检索 
	boolean isLazy();
}


通过Fieldable接口的定义,可以了解到实现该接口的Field类可以完成哪些功能了。

在Field构造好了以后,需要将每个Field添加到Document中,便于Document对Field进行管理。

Document类的源代码如下所示:

package org.apache.lucene.document;

import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.Searcher;

import java.util.*;

public final class Document implements java.io.Serializable {
	List fields = new Vector(); // 用于管理多个Field的列表 
	private float boost = 1.0f;

	// 构造一个不含有Field的Document对象 
	public Document() {
	}

	// 参看Field中说明 
	public void setBoost(float boost) {
		this.boost = boost;
	}

	public float getBoost() {
		return boost;
	}

	//   向一个Document(向量列表)中添加Field 
	public final void add(Fieldable field) {
		fields.add(field);
	}

	// 从Document中移除名称为name的Field,如果存在多个名称为name的Field,则移除第一个被添加到Document中的Field 
	public final void removeField(String name) {
		Iterator it = fields.iterator();
		while (it.hasNext()) {
			Fieldable field = (Fieldable) it.next();
			if (field.name().equals(name)) {
				it.remove();
				return;
			}
		}
	}

	// 从Document中移除名称为name的Field,如果存在多个名称为name的Field,则全部移除掉 
	public final void removeFields(String name) {
		Iterator it = fields.iterator();
		while (it.hasNext()) {
			Fieldable field = (Fieldable) it.next();
			if (field.name().equals(name)) {
				it.remove();
			}
		}
	}

	// 从Document中获取名称为name的Field,如果存在多个名称为name的Field,则返回第一个被添加到Document中的Field 
	public final Field getField(String name) {
		for (int i = 0; i < fields.size(); i++) {
			Field field = (Field) fields.get(i);
			if (field.name().equals(name))
				return field;
		}
		return null;
	}

	// 从Document中获取名称为name的Field,如果存在多个名称为name的Field,则返回第一个被添加到Document中的Field 
	public Fieldable getFieldable(String name) {
		for (int i = 0; i < fields.size(); i++) {
			Fieldable field = (Fieldable) fields.get(i);
			if (field.name().equals(name))
				return field;
		}
		return null;
	}

	// 从Document中获取名称为name的Field的String串,如果存在多个名称为name的Field,则返回第一个被添加到Document中的Field的String串 
	public final String get(String name) {
		for (int i = 0; i < fields.size(); i++) {
			Fieldable field = (Fieldable) fields.get(i);
			if (field.name().equals(name) && (!field.isBinary()))
				return field.stringValue();
		}
		return null;
	}

	//   从Document中获取所有的Field,返回一个Enumeration类型 
	public final Enumeration fields() {
		return ((Vector) fields).elements();
	}

	//   从Document中获取所有的Field,返回一个List类型 
	public final List getFields() {
		return fields;
	}

	//   从Document中获取名称为name的所有Field,返回一个Field[]数组 
	public final Field[] getFields(String name) {
		List result = new ArrayList();
		for (int i = 0; i < fields.size(); i++) {
			Field field = (Field) fields.get(i);
			if (field.name().equals(name)) {
				result.add(field);
			}
		}

		if (result.size() == 0)
			return null;

		return (Field[]) result.toArray(new Field[result.size()]);
	}

	//   从Document中获取名称为name的所有Field,返回一个Fieldable[]数组 
	public Fieldable[] getFieldables(String name) {
		List result = new ArrayList();
		for (int i = 0; i < fields.size(); i++) {
			Fieldable field = (Fieldable) fields.get(i);
			if (field.name().equals(name)) {
				result.add(field);
			}
		}

		if (result.size() == 0)
			return null;

		return (Fieldable[]) result.toArray(new Fieldable[result.size()]);
	}

	///   从Document中获取名称为name的所有Field的字符串值,返回一个字符串数组 
	public final String[] getValues(String name) {
		List result = new ArrayList();
		for (int i = 0; i < fields.size(); i++) {
			Fieldable field = (Fieldable) fields.get(i);
			if (field.name().equals(name) && (!field.isBinary()))
				result.add(field.stringValue());
		}

		if (result.size() == 0)
			return null;

		return (String[]) result.toArray(new String[result.size()]);
	}

	//   从Document中获取名称为name的所有Field的byte[] 的数组值,返回一个byte[][]数组 
	public final byte[][] getBinaryValues(String name) {
		List result = new ArrayList();
		for (int i = 0; i < fields.size(); i++) {
			Fieldable field = (Fieldable) fields.get(i);
			if (field.name().equals(name) && (field.isBinary()))
				result.add(field.binaryValue());
		}

		if (result.size() == 0)
			return null;

		return (byte[][]) result.toArray(new byte[result.size()][]);
	}

	//   从Document中获取名称为name的所有Field的byte字节值,返回一个byte[]数组 
	public final byte[] getBinaryValue(String name) {
		for (int i = 0; i < fields.size(); i++) {
			Fieldable field = (Fieldable) fields.get(i);
			if (field.name().equals(name) && (field.isBinary()))
				return field.binaryValue();
		}
		return null;
	}

	//   输出Document中所有Field的名称(以字符串的形式) 
	public final String toString() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("Document<");
		for (int i = 0; i < fields.size(); i++) {
			Fieldable field = (Fieldable) fields.get(i);
			buffer.append(field.toString());
			if (i != fields.size() - 1)
				buffer.append(" ");
		}
		buffer.append(">");
		return buffer.toString();
	}
}


Document类的最后一个方法,输出了一个Document中的所有的Field的信息,以字符串的形式输出,这个可以在检索的时候,看到具体检索关键字检索到的信息的详情,可以在文章 Lucene-2.2.0 源代码阅读学习(4) 中看到输出示例。

做个简单的例子:

直接在程序中通过字符串构造Field。

测试的主函数代码如下所示:

package org.shirdrn.lucene;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;

public class DcoumentAndField {
	public static void main(String[] args) {
		Document doc = new Document();
		Field f1 = new Field("检索", "不以物喜,不以己悲。", Field.Store.YES,
				Field.Index.TOKENIZED);
		Field f2 = new Field("雅诗", "衣带渐宽终不悔,为伊消得人憔悴。", Field.Store.NO,
				Field.Index.UN_TOKENIZED);
		Field f3 = new Field("娱乐", "某某透露,最终决定,要坚持走出一条属于自己的人生路。",
				Field.Store.NO, Field.Index.NO_NORMS);
		Field f4 = new Field("娱乐", "百度的门户建设,应该是一件不容忽视的事件。", Field.Store.NO,
				Field.Index.NO_NORMS);
		doc.add(f1);
		doc.add(f2);
		doc.add(f3);
		doc.add(f4);
		System.out.println("所有的Field信息 :" + doc.toString());
		System.out.println("获取指定Field信息:" + doc.get("雅诗"));
		System.out.println("获取指定Field信息:" + doc.getField("检索"));
		System.out.println("指定Field信息[0]:" + doc.getValues("娱乐")[0]);
		System.out.println("指定Field信息[1]:" + doc.getValues("娱乐")[1]);
	}
}



运行结程序,输出结果如下所示:

所有的Field信息:Document<stored/uncompressed,indexed,tokenized<检索:不以物喜,不以己悲。> indexed<雅诗:衣带渐宽终不悔,为伊消得人憔悴。> indexed,omitNorms<娱乐:某某透露,最终决定,要坚持走出一条属于自己的人生路。> indexed,omitNorms<娱乐:百度的门户建设,应该是一件不容忽视的事件。>>
获取指定Field信息:衣带渐宽终不悔,为伊消得人憔悴。
获取指定Field信息:stored/uncompressed,indexed,tokenized<检索:不以物喜,不以己悲。>
指定Field信息[0]:某某透露,最终决定,要坚持走出一条属于自己的人生路。
指定Field信息[1]:百度的门户建设,应该是一件不容忽视的事件。

 

到目前为止,已经对Field和Document很熟悉了。

然后,又要回到IndexWriter类了,该类特别重要,同时又是特别复杂的。IndexWriter初始化完成后,才开始了真正地建立索引的过程。建立索引是从,向一个IndexWriter实例中添加Document开始。

因此,要用到IndexWriter类的一些有用的方法了。
分享到:
评论

相关推荐

    【分享:lucene学习资料】---<下载不扣分,回帖加1分,欢迎下载,童叟无欺>

    1&gt; lucene学习笔记 2&gt; 全文检索的实现机制 【1】lucene学习笔记的目录如下 1. 概述 3 2. lucene 的包结构 3 3. 索引文件格式 3 4. lucene中主要的类 4 4.1. Document文档类 4 4.1.1. 常用方法 4 4.1.2. 示例 4 4.2...

    lucene实例

    在"20章"这个文件中,可能包含了逐步构建和使用Lucene实例的教程,涵盖了上述各个步骤的详细解释和代码示例。通过学习这些章节,你可以理解如何利用Lucene API处理文档的读取、分析、索引和搜索。同时,你也会学到...

    搜索篇:Struts、Lucene的Web实例

    通过学习这个教程,开发者不仅可以掌握Struts和Lucene的基础知识,还能了解到如何在实际项目中将两者有效结合,为用户提供高效、智能的搜索体验。对于想要提升Web开发技能,特别是对搜索功能有需求的开发者来说,这...

    lucene检索数据库

    5. City:城市,Varchar(20) 6. State:省份,Char(2) 7. Zip:邮编,Char(5) 8. Contract:外键,Bit(1) 建立Lucene索引的过程分为以下几个步骤: 1. **数据库连接**:使用JDBC建立与数据库的连接,获取数据库中...

    Lucene的应用

    ### Lucene的应用 #### Lucene简介 Lucene是一款由Doug Cutting开发并维护的高性能全文检索工具包,最初在2001年10月被贡献给...无论是对于初学者还是经验丰富的开发者来说,Lucene都是一个值得深入学习的技术。

    【java、lucene、python】互联网搜索引擎课程报告二:建立搜索引擎

    - **K-Means聚类**:这是一种常见的无监督学习算法,用于将大量文档自动分成若干类别。在本项目中,将500篇文档聚类成20个类别,并展示了其中最大的三个类别的代表性文档。 - **聚类结果评估**:为了验证聚类效果...

    基于lucene 4.7的迷你搜索引擎

    ReadMe里面有与运行介绍。 TextFileIndexer.java 用来建立索引,支持选择不同的分析器analyzer。 Demo.java用来运行搜索引擎。 由于版权问题,拿来建立索引的Json文件这里就不提供了,可以自行编写几条来建立索引。

    lucenes全文检索

    **Lucene 全文检索** Lucene 是一个高性能、全文本搜索库,由 Apache 软件基金会开发,被广泛应用于各种系统中的全文检索功能。它提供了强大的索引和...对于学习和实践 Lucene 全文检索,这个项目是一个很好的起点。

    Java学习的30个目标

    熟悉日志框架(如Log4J)、任务调度(如Quartz)、分布式缓存(如JCache)、全文搜索(如Lucene)等常用框架和API。 #### 21. 本地接口与连接器架构 学习Java Native Interface(JNI)和Java Connector ...

    学习java的30个目标.txt

    #### 目标20:熟悉日志记录与调度框架 - **框架选择**:Log4J、Quartz等。 - **应用场景**:日志管理、定时任务调度等。 #### 目标21:掌握网络通信与缓存技术 - **技术框架**:JGroups、JCache等。 - **应用场景...

    学习Java语言的30个参考,让你坐拥别人之上的30个擦考

    - **Lucene**:学习全文检索技术的基础知识。 ### 21. 本地接口与连接器 - **JNI、JCA**:掌握Java Native Interface、Java Connector Architecture等技术,实现Java与其他语言或平台的交互。 通过以上知识点的...

    Jeecms2012版标签学习手册

    ### Jeecms2012版标签学习手册详解 #### 一、2012版关键字标签[@cms_tag_list] **关键词标签(Tag列表标签)**主要用于在网站中展示热门或相关的标签列表,帮助用户快速定位感兴趣的内容。该标签允许自定义显示的...

    常用的开发手册,都是chm格式,帮助文档,很好用

    9. **lucene_3.6.1_API.CHM**:Apache Lucene是一个全文搜索引擎库,此文档详细介绍了Lucene 3.6.1版本的API,包括索引构建、查询解析、搜索等功能。 这些CHM文件提供了丰富的编程和Web开发知识,对于学习和提升...

    java的30个学习目标

    #### 20. **J2EE服务** - JNDI、JMS、JTA/JTS、JMX等服务提供命名目录访问、消息传递、事务管理和监控等功能。 #### 21. **JavaBeans组件(EJB)** - Stateless/Stateful Session Beans、Entity Beans、Message-...

    搜索链接类网站(多套)

    [搜索链接]java(结合lucene)版的公交搜索系统_javaso [搜索链接]Java网络爬虫(蜘蛛)源码_zhizhu [搜索链接]Mysoo站内搜索 v1.0 Peview_mysoo-1.0-preview.war [搜索链接]深度学习网址导航系统 v0.0.16(jsp)_jspurl ...

    搜索引擎开发培训课程提纲PPT学习教案.pptx

    11. **中文分词**:在Lucene和Lietu等工具中,中文分词是文本预处理的关键步骤,正向最大匹配是常见的分词算法。 12. **查找词典算法**:Trie树是构建词典和进行快速查找的高效数据结构,包括数字搜索树和Tire树,...

    java+大数据.pdf

    在JavaEE项目实战方面,可以选择支付宝内部OA系统(15天)、阿里菜鸟物流项目(20天)或淘宝商城项目(20天)进行实践,这些项目可以帮助学员将理论知识转化为实际操作经验。 接下来,计划中还包含了Linux基础(3天...

    java爬虫资料 pdf 文档 视频 源码 都有

    此外,"44 炫酷科技【20套】——亮亮图文旗舰店.rar"可能包含了更多的技术教程或资源,这为学习者提供了更广阔的视野。".torrent"文件是BitTorrent协议的种子文件,通常用于分发大型文件,如视频教程,这可能是"RS ...

    Solr学习笔记。。

    2. 查询价格在0到400之间的商品,返回id、name和price字段,并按类别进行 faceting:`http://localhost:8983/solr/select?q=price:[0%20TO%20400]&fl=id,name,price&facet=true&facet.field=cat` 通过以上步骤,你...

Global site tag (gtag.js) - Google Analytics