2021SC@SDUSC
概述
文档是索引和搜索的单位。 文档是一组字段。
每个字段都有一个名称和一个文本值。 一个字段可以与文档一起存储,
在这种情况下,它与文档上的搜索命中一起返回。
因此,每个文档通常应该包含一个或多个唯一标识它的存储字段。
Solr 的基本信息单元是一个文档,它是描述某些东西的一组数据。例如:配方文件将包含成分、说明、准备时间、烹饪时间、所需的工具等等。例如,关于一个人的文档可能包含该人的姓名、传记、最喜欢的颜色和鞋子大小。关于一本书的文档可能包含标题、作者、出版年份、页数等等。
在 Solr 宇宙中,文档由字段组成,这些字段是更具体的信息片段。我们比喻的鞋子的大小可能是一个领域,名字和姓氏可以是字段。
字段可以包含不同类型的数据。例如,名称字段是文本(字符数据)。鞋号字段可能是一个浮点数,以便它可以包含像 6 和 9.5 这样的值。显然,字段的定义是非常灵活的(例如,您可以将鞋号字段定义为文本字段而不是浮点数),但是如果您正确定义字段,Solr 将能够正确解释它们,并且您的用户在执行查询时会得到更好的结果。
您可以通过指定字段类型来告诉 Solr 字段包含的数据类型。字段类型告诉 Solr 如何解释字段以及如何查询。
当您添加一个文档时,Solr 将获取文档字段中的信息并将该信息添加到索引中。当您执行查询时,Solr 可以快速查阅索引并返回匹配的文档。
代码分析
(详见代码片中内容)
package org.apache.lucene.document;
import java.util.*;
import org.apache.lucene.index.IndexReader; // for javadoc
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.search.IndexSearcher; // for javadoc
import org.apache.lucene.search.ScoreDoc; // for javadoc
import org.apache.lucene.util.BytesRef;
/** Documents are the unit of indexing and search.
*
*
* 文档是索引和搜索的单位。 文档是一组字段。
* 每个字段都有一个名称和一个文本值。 一个字段可以与文档一起存储,
* 在这种情况下,它与文档上的搜索命中一起返回。
* 因此,每个文档通常应该包含一个或多个唯一标识它的存储字段。
*
*/
public final class Document implements Iterable<IndexableField> {
private final List<IndexableField> fields = new ArrayList<>();
/** Constructs a new document with no fields. */
public Document() {}
/*
创建迭代器
*/
@Override
public Iterator<IndexableField> iterator() {
return fields.iterator();
}
/**
* 向文档添加字段。 可以添加多个具有相同名称的字段。
* 在这种情况下,如果字段被索引,它们的文本被视为为了搜索目的而附加。
*/
public final void add(IndexableField field) {
fields.add(field);
}
/**
* 从文档中删除具有指定名称的字段。
* 如果存在多个具有此名称的字段,则此方法将删除已添加的第一个字段。
* 如果没有指定名称的字段,则文档保持不变。
*/
public final void removeField(String name) {
Iterator<IndexableField> it = fields.iterator();
while (it.hasNext()) {
IndexableField field = it.next();
if (field.name().equals(name)) {
it.remove();
return;
}
}
}
/**
*
* 从文档中删除具有给定名称的所有字段。
* 如果没有指定名称的字段,则文档保持不变。
*/
public final void removeFields(String name) {
Iterator<IndexableField> it = fields.iterator();
while (it.hasNext()) {
IndexableField field = it.next();
if (field.name().equals(name)) {
it.remove();
}
}
}
/**
*返回名称指定为方法参数的字段的字节数组数组。
*此方法返回一个空
*没有匹配字段时的数组。 它永远不会返回 null。
* @param name the name of the field
* @return a <code>BytesRef[]</code> of binary field values
*/
public final BytesRef[] getBinaryValues(String name) {
final List<BytesRef> result = new ArrayList<>();
for (IndexableField field : fields) {
if (field.name().equals(name)) {
final BytesRef bytes = field.binaryValue();
if (bytes != null) {
result.add(bytes);
}
}
}
return result.toArray(new BytesRef[result.size()]);
}
/**
*返回具有名称的第一个(或唯一)字段的字节数组
*指定为方法参数。 如果没有指定名称的二进制字段可用,则此方法将返回
*<code>null</code>。
*可能存在同名的非二进制字段。
* @param name the name of the field.
* @return a <code>BytesRef</code> containing the binary field value or <code>null</code>
*/
public final BytesRef getBinaryValue(String name) {
for (IndexableField field : fields) {
if (field.name().equals(name)) {
final BytesRef bytes = field.binaryValue();
if (bytes != null) {
return bytes;
}
}
}
return null;
}
/**
* 如果此文档中存在,则返回具有给定名称的字段,否则返回 null。
*如果存在多个具有此名称的字段,则此方法返回添加的第一个值。
*/
public final IndexableField getField(String name) {
for (IndexableField field : fields) {
if (field.name().equals(name)) {
return field;
}
}
return null;
}
/**
* 返回具有给定名称的 {@link IndexableField} 数组。
*当没有匹配的字段时,此方法返回一个空数组。 它永远不会返回 null。
*
* @param name the name of the field
* @return a <code>Field[]</code> array
*/
public IndexableField[] getFields(String name) {
List<IndexableField> result = new ArrayList<>();
for (IndexableField field : fields) {
if (field.name().equals(name)) {
result.add(field);
}
}
return result.toArray(new IndexableField[result.size()]);
}
/**
* 返回文档中所有字段的列表。
*<p>请注意,<i>not</i> 存储的字段在从索引检索的文档中 <i>not</i> 可用,
例如 {@link IndexSearcher#doc(int)} 或{@linkIndexReader#document(int)}。
* @return an immutable <code>List<Field></code>
*/
public final List<IndexableField> getFields() {
return Collections.unmodifiableList(fields);
}
private final static String[] NO_STRINGS = new String[0];
/**
* Returns an array of values of the field specified as the method parameter.
* This method returns an empty array when there are no
* matching fields. It never returns null.
* For a numeric {@link StoredField} it returns the string value of the number. If you want
* the actual numeric field instances back, use {@link #getFields}.
* @param name the name of the field
* @return a <code>String[]</code> of field values
*/
public final String[] getValues(String name) {
List<String> result = new ArrayList<>();
for (IndexableField field : fields) {
if (field.name().equals(name) && field.stringValue() != null) {
result.add(field.stringValue());
}
}
if (result.size() == 0) {
return NO_STRINGS;
}
return result.toArray(new String[result.size()]);
}
/**
* 返回指定为方法参数的字段值的数组。
*当没有匹配的字段时,此方法返回一个空数组。
*它永远不会返回 null。
*对于数字 {@link StoredField},它返回实际数字字段实例的字符串值,
*使用 {@link #getFields}。
*/
public final String get(String name) {
for (IndexableField field : fields) {
if (field.name().equals(name) && field.stringValue() != null) {
return field.stringValue();
}
}
return null;
}
/**
*打印供人类使用的字段
*/
@Override
public final String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("Document<");
for (int i = 0; i < fields.size(); i++) {
IndexableField field = fields.get(i);
buffer.append(field.toString());
if (i != fields.size()-1) {
buffer.append(" ");
}
}
buffer.append(">");
return buffer.toString();
}
/** Removes all the fields from document. */
public void clear() {
fields.clear();
}
}