blob: bf91303b991c28d26b9be57894b0139a9e6981ea [file] [log] [blame]
Index: src/test/org/apache/lucene/index/TestFieldsReader.java
===================================================================
--- src/test/org/apache/lucene/index/TestFieldsReader.java (revision 382415)
+++ src/test/org/apache/lucene/index/TestFieldsReader.java (working copy)
@@ -69,7 +69,39 @@
assertTrue(field.isStorePositionWithTermVector() == false);
assertTrue(field.getOmitNorms() == true);
-
reader.close();
}
+
+ public void testDocField() throws IOException {
+ assertTrue(dir != null);
+ assertTrue(fieldInfos != null);
+ FieldsReader reader = new FieldsReader(dir, "test", fieldInfos);
+ assertTrue(reader != null);
+ assertTrue(reader.size() == 1);
+
+ Field field = reader.docField(0,"textField1");
+ assertTrue(field != null);
+ assertEquals(DocHelper.FIELD_1_TEXT, field.stringValue());
+
+ field = reader.docField(0,"textField2");
+ assertTrue(field != null);
+ assertTrue(field.isTermVectorStored() == true);
+
+ assertTrue(field.isStoreOffsetWithTermVector() == true);
+ assertTrue(field.isStorePositionWithTermVector() == true);
+ assertTrue(field.getOmitNorms() == false);
+ assertEquals(DocHelper.FIELD_2_TEXT, field.stringValue());
+
+ field = reader.docField(0, "textField3");
+ assertTrue(field != null);
+ assertTrue(field.isTermVectorStored() == false);
+ assertTrue(field.isStoreOffsetWithTermVector() == false);
+ assertTrue(field.isStorePositionWithTermVector() == false);
+ assertTrue(field.getOmitNorms() == true);
+ assertEquals(DocHelper.FIELD_3_TEXT, field.stringValue());
+
+ assertTrue(reader.docField(0,"doesnotexist") == null);
+
+ reader.close();
+ }
}
Index: src/java/org/apache/lucene/index/FieldsReader.java
===================================================================
--- src/java/org/apache/lucene/index/FieldsReader.java (revision 382415)
+++ src/java/org/apache/lucene/index/FieldsReader.java (working copy)
@@ -57,6 +57,11 @@
return size;
}
+ /**
+ * Retrieve a Document that contains all of the fields defined in the index
+ * @param n the document number
+ * @return
+ */
final Document doc(int n) throws IOException {
indexStream.seek(n * 8L);
long position = indexStream.readLong();
@@ -67,9 +72,22 @@
for (int i = 0; i < numFields; i++) {
int fieldNumber = fieldsStream.readVInt();
FieldInfo fi = fieldInfos.fieldInfo(fieldNumber);
+ doc.add(getFieldFromStream(fi));
+ }
+ return doc;
+ }
+
+ /**
+ * Retrive a particular field from fieldsStream, which is currently
+ * looking at the bits byte of a field. When finished, the fieldStream
+ * will be looking at the fieldNum of the next stored field.
+ * @param fi the FieldInfo for the field being examined (based on the
+ * previous vint in the stream)
+ * @return the <tt>Field</tt>.
+ */
+ private Field getFieldFromStream(FieldInfo fi) throws IOException {
byte bits = fieldsStream.readByte();
-
boolean compressed = (bits & FieldsWriter.FIELD_IS_COMPRESSED) != 0;
boolean tokenize = (bits & FieldsWriter.FIELD_IS_TOKENIZED) != 0;
@@ -77,9 +95,9 @@
final byte[] b = new byte[fieldsStream.readVInt()];
fieldsStream.readBytes(b, 0, b.length);
if (compressed)
- doc.add(new Field(fi.name, uncompress(b), Field.Store.COMPRESS));
+ return new Field(fi.name, uncompress(b), Field.Store.COMPRESS);
else
- doc.add(new Field(fi.name, b, Field.Store.YES));
+ return new Field(fi.name, b, Field.Store.YES);
}
else {
Field.Index index;
@@ -123,7 +141,7 @@
index,
termVector);
f.setOmitNorms(fi.omitNorms);
- doc.add(f);
+ return f;
}
else {
Field f = new Field(fi.name, // name
@@ -132,13 +150,53 @@
index,
termVector);
f.setOmitNorms(fi.omitNorms);
- doc.add(f);
+ return f;
}
}
- }
+ }
- return doc;
+ /**
+ * Retrieve the first field in the given document with the
+ * specified field name. If there are more than one field
+ * in the document with that field name, only the first one
+ * is returned.
+ * @param n the document to retrieve
+ * @param fieldName the name of the field to retrieve
+ * @return the first field in the document with that name, or <tt>null</tt>
+ * if the document doesn't have such a field stored.
+ * @see Document#getField(String)
+ * @throws IOException
+ */
+ final Field docField(int n, String fieldName) throws IOException {
+ int fieldNo = fieldInfos.fieldNumber(fieldName);
+ if (fieldNo < 0) return null;
+
+ // Seek to the start of all the fields
+ indexStream.seek(n * 8L);
+ long position = indexStream.readLong();
+ fieldsStream.seek(position);
+
+ int numFields = fieldsStream.readVInt();
+
+ for (int i = 0; i < numFields; i++) {
+ int fieldNumber = fieldsStream.readVInt();
+ if (fieldNumber == fieldNo) {
+ // This is the field we want
+ FieldInfo fi = fieldInfos.fieldInfo(fieldNumber);
+ return getFieldFromStream(fi);
+ } else {
+ // This is the field we want to skip
+ fieldsStream.readByte(); // The bits
+ int dataLength = fieldsStream.readVInt(); // Length to skip;
+ fieldsStream.seek(fieldsStream.getFilePointer() + dataLength);
+ continue;
+ }
+
+ }
+ // The field wasn't defined on the document, so ignore it.
+ return null;
}
+
private final byte[] uncompress(final byte[] input)
throws IOException
Index: src/java/org/apache/lucene/index/IndexReader.java
===================================================================
--- src/java/org/apache/lucene/index/IndexReader.java (revision 382415)
+++ src/java/org/apache/lucene/index/IndexReader.java (working copy)
@@ -357,6 +357,20 @@
<code>Document</code> in this index. */
public abstract Document document(int n) throws IOException;
+ /**
+ * Return the document field for the given document. If querying for
+ * only one field on a document, implementations may make this more efficient
+ * that calling document(doc).getField(field). It will only return the
+ * first value of the field in the document, like {@link Document#getField(String)}
+ *
+ * Only use this function if you know there can be only one value for the field
+ * (like a document id), this is the only field you want,
+ * and you want to reduce the overhead of querying.
+ */
+ public Field getDocField(int doc, String field) throws IOException {
+ return document(doc).getField(field);
+ }
+
/** Returns true if document <i>n</i> has been deleted */
public abstract boolean isDeleted(int n);
Index: src/java/org/apache/lucene/index/SegmentReader.java
===================================================================
--- src/java/org/apache/lucene/index/SegmentReader.java (revision 382415)
+++ src/java/org/apache/lucene/index/SegmentReader.java (working copy)
@@ -284,6 +284,13 @@
return fieldsReader.doc(n);
}
+ public Field getDocField(int doc, String fieldName) throws IOException {
+ if (isDeleted(doc))
+ throw new IllegalArgumentException
+ ("attempt to access a deleted document");
+ return fieldsReader.docField(doc, fieldName);
+ }
+
public synchronized boolean isDeleted(int n) {
return (deletedDocs != null && deletedDocs.get(n));
}