| diff --git a/lucene/core/src/java/org/apache/lucene/document/FieldType.java b/lucene/core/src/java/org/apache/lucene/document/FieldType.java |
| index a21572e96c..cdf01e1626 100644 |
| --- a/lucene/core/src/java/org/apache/lucene/document/FieldType.java |
| +++ b/lucene/core/src/java/org/apache/lucene/document/FieldType.java |
| @@ -17,6 +17,9 @@ |
| package org.apache.lucene.document; |
| |
| |
| +import java.util.HashMap; |
| +import java.util.Map; |
| + |
| import org.apache.lucene.analysis.Analyzer; // javadocs |
| import org.apache.lucene.index.DocValuesType; |
| import org.apache.lucene.index.IndexOptions; |
| @@ -41,6 +44,7 @@ public class FieldType implements IndexableFieldType { |
| private int dataDimensionCount; |
| private int indexDimensionCount; |
| private int dimensionNumBytes; |
| + private Map<String, String> attributes = null; |
| |
| /** |
| * Create a new mutable FieldType with all of the properties from <code>ref</code> |
| @@ -58,6 +62,7 @@ public class FieldType implements IndexableFieldType { |
| this.dataDimensionCount = ref.pointDataDimensionCount(); |
| this.indexDimensionCount = ref.pointIndexDimensionCount(); |
| this.dimensionNumBytes = ref.pointNumBytes(); |
| + this.attributes = ref.getAttributes(); |
| // Do not copy frozen! |
| } |
| |
| @@ -341,6 +346,30 @@ public class FieldType implements IndexableFieldType { |
| return dimensionNumBytes; |
| } |
| |
| + /** |
| + * Puts an attribute value. |
| + * <p> |
| + * This is a key-value mapping for the field that the codec can use |
| + * to store additional metadata. |
| + * <p> |
| + * If a value already exists for the field, it will be replaced with |
| + * the new value. This method is not thread-safe, user must not add attributes |
| + * while other threads are indexing documents with this field type. |
| + * |
| + * @lucene.experimental |
| + */ |
| + public String putAttribute(String key, String value) { |
| + if (attributes == null) { |
| + attributes = new HashMap<>(); |
| + } |
| + return attributes.put(key, value); |
| + } |
| + |
| + @Override |
| + public Map<String, String> getAttributes() { |
| + return attributes; |
| + } |
| + |
| /** Prints a Field for human consumption. */ |
| @Override |
| public String toString() { |
| diff --git a/lucene/core/src/java/org/apache/lucene/index/DefaultIndexingChain.java b/lucene/core/src/java/org/apache/lucene/index/DefaultIndexingChain.java |
| index 4cc981dbd7..91a69cf2f1 100644 |
| --- a/lucene/core/src/java/org/apache/lucene/index/DefaultIndexingChain.java |
| +++ b/lucene/core/src/java/org/apache/lucene/index/DefaultIndexingChain.java |
| @@ -661,6 +661,10 @@ final class DefaultIndexingChain extends DocConsumer { |
| |
| FieldInfo fi = fieldInfos.getOrAdd(name); |
| initIndexOptions(fi, fieldType.indexOptions()); |
| + if (fieldType.getAttributes() != null) { |
| + fieldType.getAttributes().forEach((k, v) -> fi.putAttribute(k, v)); |
| + } |
| + |
| fp = new PerField(docWriter.getIndexCreatedVersionMajor(), fi, invert); |
| fp.next = fieldHash[hashPos]; |
| fieldHash[hashPos] = fp; |
| diff --git a/lucene/core/src/java/org/apache/lucene/index/IndexableFieldType.java b/lucene/core/src/java/org/apache/lucene/index/IndexableFieldType.java |
| index b2b2e773ca..59c5ab5192 100644 |
| --- a/lucene/core/src/java/org/apache/lucene/index/IndexableFieldType.java |
| +++ b/lucene/core/src/java/org/apache/lucene/index/IndexableFieldType.java |
| @@ -17,6 +17,8 @@ |
| package org.apache.lucene.index; |
| |
| |
| +import java.util.Map; |
| + |
| import org.apache.lucene.analysis.Analyzer; // javadocs |
| |
| /** |
| @@ -111,4 +113,14 @@ public interface IndexableFieldType { |
| * The number of bytes in each dimension's values. |
| */ |
| public int pointNumBytes(); |
| + |
| + /** |
| + * Attributes for the field type. |
| + * |
| + * Attributes are not thread-safe, user must not add attributes while other threads are indexing documents |
| + * with this field type. |
| + * |
| + * @return Map |
| + */ |
| + public Map<String, String> getAttributes(); |
| } |
| diff --git a/lucene/core/src/test/org/apache/lucene/index/TestFieldInfos.java b/lucene/core/src/test/org/apache/lucene/index/TestFieldInfos.java |
| index 3fe5fa9d2c..79fb5abae7 100644 |
| --- a/lucene/core/src/test/org/apache/lucene/index/TestFieldInfos.java |
| +++ b/lucene/core/src/test/org/apache/lucene/index/TestFieldInfos.java |
| @@ -23,6 +23,7 @@ import java.util.Iterator; |
| import org.apache.lucene.analysis.MockAnalyzer; |
| import org.apache.lucene.document.Document; |
| import org.apache.lucene.document.Field; |
| +import org.apache.lucene.document.FieldType; |
| import org.apache.lucene.document.StringField; |
| import org.apache.lucene.store.Directory; |
| import org.apache.lucene.util.LuceneTestCase; |
| @@ -93,6 +94,32 @@ public class TestFieldInfos extends LuceneTestCase { |
| dir.close(); |
| } |
| |
| + public void testFieldAttributes() throws Exception{ |
| + Directory dir = newDirectory(); |
| + IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(new MockAnalyzer(random())) |
| + .setMergePolicy(NoMergePolicy.INSTANCE)); |
| + |
| + Document d = new Document(); |
| + FieldType type = new FieldType(); |
| + type.setStored(true); |
| + type.putAttribute("testKey", "testValue"); |
| + d.add(new Field("f", "v", type)); |
| + writer.addDocument(d); |
| + writer.commit(); |
| + writer.close(); |
| + |
| + SegmentInfos sis = SegmentInfos.readLatestCommit(dir); |
| + FieldInfos fis = IndexWriter.readFieldInfos(sis.info(0)); |
| + Iterator<FieldInfo> it = fis.iterator(); |
| + while(it.hasNext()) { |
| + FieldInfo fi = it.next(); |
| + assertEquals(0, fi.number); |
| + assertEquals("f", fi.name); |
| + assertEquals("testValue", fi.getAttribute("testKey")); |
| + } |
| + dir.close(); |
| + } |
| + |
| public void testMergedFieldInfos_empty() throws IOException { |
| Directory dir = newDirectory(); |
| IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(new MockAnalyzer(random()))); |
| diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexableField.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexableField.java |
| index 1091b2485e..59dbae3cd7 100644 |
| --- a/lucene/core/src/test/org/apache/lucene/index/TestIndexableField.java |
| +++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexableField.java |
| @@ -21,6 +21,7 @@ import java.io.Reader; |
| import java.io.StringReader; |
| import java.util.Collections; |
| import java.util.Iterator; |
| +import java.util.Map; |
| |
| import org.apache.lucene.analysis.Analyzer; |
| import org.apache.lucene.analysis.TokenStream; |
| @@ -104,6 +105,11 @@ public class TestIndexableField extends LuceneTestCase { |
| public int pointNumBytes() { |
| return 0; |
| } |
| + |
| + @Override |
| + public Map<String, String> getAttributes() { |
| + return null; |
| + } |
| }; |
| |
| public MyField(int counter) { |
| diff --git a/solr/core/src/java/org/apache/solr/schema/SchemaField.java b/solr/core/src/java/org/apache/solr/schema/SchemaField.java |
| index 7d9449e6d9..100a963c1c 100644 |
| --- a/solr/core/src/java/org/apache/solr/schema/SchemaField.java |
| +++ b/solr/core/src/java/org/apache/solr/schema/SchemaField.java |
| @@ -430,4 +430,9 @@ public final class SchemaField extends FieldProperties implements IndexableField |
| public int pointNumBytes() { |
| return 0; |
| } |
| + |
| + @Override |
| + public Map<String, String> getAttributes() { |
| + return null; |
| + } |
| } |