mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-28 19:08:40 +00:00
add the ability to define meta _attributes for mapping, basically a place to store additional unstructured data on the mapping
This commit is contained in:
parent
3770924300
commit
cb9be9973b
modules/elasticsearch/src
main/java/org/elasticsearch
cluster/metadata
index/mapper
test/java/org/elasticsearch/index/mapper/xcontent/simple
@ -226,7 +226,7 @@ public class MetaDataService extends AbstractComponent {
|
|||||||
.initializeEmpty(newMetaData.index(index));
|
.initializeEmpty(newMetaData.index(index));
|
||||||
routingTableBuilder.add(indexRoutingBuilder);
|
routingTableBuilder.add(indexRoutingBuilder);
|
||||||
|
|
||||||
logger.info("creating index [{}], cause [{}], shards [{}]/[{}], mappings {}", index, cause, indexMetaData.numberOfShards(), indexMetaData.numberOfReplicas(), fMappings.keySet());
|
logger.info("[{}] creating index, cause [{}], shards [{}]/[{}], mappings {}", index, cause, indexMetaData.numberOfShards(), indexMetaData.numberOfReplicas(), fMappings.keySet());
|
||||||
RoutingTable newRoutingTable = shardsRoutingStrategy.reroute(newClusterStateBuilder().state(currentState).routingTable(routingTableBuilder).metaData(newMetaData).build());
|
RoutingTable newRoutingTable = shardsRoutingStrategy.reroute(newClusterStateBuilder().state(currentState).routingTable(routingTableBuilder).metaData(newMetaData).build());
|
||||||
return newClusterStateBuilder().state(currentState).routingTable(newRoutingTable).metaData(newMetaData).build();
|
return newClusterStateBuilder().state(currentState).routingTable(newRoutingTable).metaData(newMetaData).build();
|
||||||
}
|
}
|
||||||
@ -265,7 +265,7 @@ public class MetaDataService extends AbstractComponent {
|
|||||||
throw new IndexMissingException(new Index(index));
|
throw new IndexMissingException(new Index(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("deleting index [{}]", index);
|
logger.info("[{}] deleting index", index);
|
||||||
|
|
||||||
final CountDownLatch latch = new CountDownLatch(clusterService.state().nodes().size());
|
final CountDownLatch latch = new CountDownLatch(clusterService.state().nodes().size());
|
||||||
NodeIndexDeletedAction.Listener listener = new NodeIndexDeletedAction.Listener() {
|
NodeIndexDeletedAction.Listener listener = new NodeIndexDeletedAction.Listener() {
|
||||||
@ -320,9 +320,9 @@ public class MetaDataService extends AbstractComponent {
|
|||||||
// build the updated mapping source
|
// build the updated mapping source
|
||||||
final String updatedMappingSource = existingMapper.buildSource();
|
final String updatedMappingSource = existingMapper.buildSource();
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("index [" + index + "]: Update mapping [" + type + "] (dynamic) with source [" + updatedMappingSource + "]");
|
logger.debug("[{}] update mapping [{}] (dynamic) with source [{}]", index, type, updatedMappingSource);
|
||||||
} else if (logger.isInfoEnabled()) {
|
} else if (logger.isInfoEnabled()) {
|
||||||
logger.info("index [" + index + "]: Update mapping [" + type + "] (dynamic)");
|
logger.info("[{}] update mapping [{}] (dynamic)", index, type);
|
||||||
}
|
}
|
||||||
// publish the new mapping
|
// publish the new mapping
|
||||||
clusterService.submitStateUpdateTask("update-mapping [" + index + "][" + type + "]", new ClusterStateUpdateTask() {
|
clusterService.submitStateUpdateTask("update-mapping [" + index + "][" + type + "]", new ClusterStateUpdateTask() {
|
||||||
@ -396,9 +396,9 @@ public class MetaDataService extends AbstractComponent {
|
|||||||
}
|
}
|
||||||
mappings.put(index, mapping);
|
mappings.put(index, mapping);
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("index [" + index + "]: Put mapping [" + mapping.v1() + "] with source [" + mapping.v2() + "]");
|
logger.debug("[{}] put_mapping [{}] with source [{}]", index, mapping.v1(), mapping.v2());
|
||||||
} else if (logger.isInfoEnabled()) {
|
} else if (logger.isInfoEnabled()) {
|
||||||
logger.info("index [" + index + "]: Put mapping [" + mapping.v1() + "]");
|
logger.info("[{}] put_mapping [{}]", index, mapping.v1());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ package org.elasticsearch.index.mapper;
|
|||||||
|
|
||||||
import org.apache.lucene.analysis.Analyzer;
|
import org.apache.lucene.analysis.Analyzer;
|
||||||
import org.apache.lucene.document.Fieldable;
|
import org.apache.lucene.document.Fieldable;
|
||||||
|
import org.elasticsearch.common.collect.ImmutableMap;
|
||||||
import org.elasticsearch.common.util.concurrent.ThreadSafe;
|
import org.elasticsearch.common.util.concurrent.ThreadSafe;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -39,6 +40,11 @@ public interface DocumentMapper {
|
|||||||
*/
|
*/
|
||||||
String mappingSource();
|
String mappingSource();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attributes of this type mappings.
|
||||||
|
*/
|
||||||
|
ImmutableMap<String, Object> attributes();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the source of the mapper based on the current mappings.
|
* Generates the source of the mapper based on the current mappings.
|
||||||
*/
|
*/
|
||||||
|
@ -46,7 +46,7 @@ import java.net.URL;
|
|||||||
import static org.elasticsearch.common.collect.MapBuilder.*;
|
import static org.elasticsearch.common.collect.MapBuilder.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kimchy (Shay Banon)
|
* @author kimchy (shay.banon)
|
||||||
*/
|
*/
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
public class MapperService extends AbstractIndexComponent implements Iterable<DocumentMapper> {
|
public class MapperService extends AbstractIndexComponent implements Iterable<DocumentMapper> {
|
||||||
@ -60,8 +60,6 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
|
|||||||
|
|
||||||
private final URL dynamicMappingUrl;
|
private final URL dynamicMappingUrl;
|
||||||
|
|
||||||
private final ClassLoader indexClassLoader;
|
|
||||||
|
|
||||||
private final String dynamicMappingSource;
|
private final String dynamicMappingSource;
|
||||||
|
|
||||||
private volatile ImmutableMap<String, DocumentMapper> mappers = ImmutableMap.of();
|
private volatile ImmutableMap<String, DocumentMapper> mappers = ImmutableMap.of();
|
||||||
@ -87,7 +85,6 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
|
|||||||
super(index, indexSettings);
|
super(index, indexSettings);
|
||||||
this.documentParser = new XContentDocumentMapperParser(analysisService);
|
this.documentParser = new XContentDocumentMapperParser(analysisService);
|
||||||
this.searchAnalyzer = new SmartIndexNameSearchAnalyzer(analysisService.defaultSearchAnalyzer());
|
this.searchAnalyzer = new SmartIndexNameSearchAnalyzer(analysisService.defaultSearchAnalyzer());
|
||||||
this.indexClassLoader = indexSettings.getClassLoader();
|
|
||||||
|
|
||||||
this.dynamic = componentSettings.getAsBoolean("dynamic", true);
|
this.dynamic = componentSettings.getAsBoolean("dynamic", true);
|
||||||
String dynamicMappingLocation = componentSettings.get("dynamic_mapping_location");
|
String dynamicMappingLocation = componentSettings.get("dynamic_mapping_location");
|
||||||
@ -97,7 +94,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
|
|||||||
dynamicMappingUrl = environment.resolveConfig("dynamic-mapping.json");
|
dynamicMappingUrl = environment.resolveConfig("dynamic-mapping.json");
|
||||||
} catch (FailedToResolveConfigException e) {
|
} catch (FailedToResolveConfigException e) {
|
||||||
// not there, default to the built in one
|
// not there, default to the built in one
|
||||||
dynamicMappingUrl = indexClassLoader.getResource("org/elasticsearch/index/mapper/xcontent/dynamic-mapping.json");
|
dynamicMappingUrl = indexSettings.getClassLoader().getResource("org/elasticsearch/index/mapper/xcontent/dynamic-mapping.json");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
@ -127,7 +124,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
|
|||||||
} else {
|
} else {
|
||||||
dynamicMappingSource = null;
|
dynamicMappingSource = null;
|
||||||
}
|
}
|
||||||
logger.debug("Using dynamic[{}] with location[{}] and source[{}]", new Object[]{dynamic, dynamicMappingLocation, dynamicMappingSource});
|
logger.debug("using dynamic[{}] with location[{}] and source[{}]", dynamic, dynamicMappingLocation, dynamicMappingSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public UnmodifiableIterator<DocumentMapper> iterator() {
|
@Override public UnmodifiableIterator<DocumentMapper> iterator() {
|
||||||
|
@ -22,6 +22,7 @@ package org.elasticsearch.index.mapper.xcontent;
|
|||||||
import org.apache.lucene.analysis.Analyzer;
|
import org.apache.lucene.analysis.Analyzer;
|
||||||
import org.apache.lucene.document.Document;
|
import org.apache.lucene.document.Document;
|
||||||
import org.elasticsearch.common.Preconditions;
|
import org.elasticsearch.common.Preconditions;
|
||||||
|
import org.elasticsearch.common.collect.ImmutableMap;
|
||||||
import org.elasticsearch.common.thread.ThreadLocals;
|
import org.elasticsearch.common.thread.ThreadLocals;
|
||||||
import org.elasticsearch.common.xcontent.ToXContent;
|
import org.elasticsearch.common.xcontent.ToXContent;
|
||||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
@ -64,12 +65,19 @@ public class XContentDocumentMapper implements DocumentMapper, ToXContent {
|
|||||||
|
|
||||||
private String mappingSource;
|
private String mappingSource;
|
||||||
|
|
||||||
|
private ImmutableMap<String, Object> attributes = ImmutableMap.of();
|
||||||
|
|
||||||
private XContentMapper.BuilderContext builderContext = new XContentMapper.BuilderContext(new ContentPath(1));
|
private XContentMapper.BuilderContext builderContext = new XContentMapper.BuilderContext(new ContentPath(1));
|
||||||
|
|
||||||
public Builder(XContentObjectMapper.Builder builder) {
|
public Builder(XContentObjectMapper.Builder builder) {
|
||||||
this.rootObjectMapper = builder.build(builderContext);
|
this.rootObjectMapper = builder.build(builderContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder attributes(ImmutableMap<String, Object> attributes) {
|
||||||
|
this.attributes = attributes;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Builder sourceField(XContentSourceFieldMapper.Builder builder) {
|
public Builder sourceField(XContentSourceFieldMapper.Builder builder) {
|
||||||
this.sourceFieldMapper = builder.build(builderContext);
|
this.sourceFieldMapper = builder.build(builderContext);
|
||||||
return this;
|
return this;
|
||||||
@ -125,7 +133,7 @@ public class XContentDocumentMapper implements DocumentMapper, ToXContent {
|
|||||||
|
|
||||||
public XContentDocumentMapper build() {
|
public XContentDocumentMapper build() {
|
||||||
Preconditions.checkNotNull(rootObjectMapper, "Mapper builder must have the root object mapper set");
|
Preconditions.checkNotNull(rootObjectMapper, "Mapper builder must have the root object mapper set");
|
||||||
return new XContentDocumentMapper(rootObjectMapper, uidFieldMapper, idFieldMapper, typeFieldMapper,
|
return new XContentDocumentMapper(rootObjectMapper, attributes, uidFieldMapper, idFieldMapper, typeFieldMapper,
|
||||||
sourceFieldMapper, allFieldMapper, indexAnalyzer, searchAnalyzer, boostFieldMapper, mappingSource);
|
sourceFieldMapper, allFieldMapper, indexAnalyzer, searchAnalyzer, boostFieldMapper, mappingSource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,6 +147,8 @@ public class XContentDocumentMapper implements DocumentMapper, ToXContent {
|
|||||||
|
|
||||||
private final String type;
|
private final String type;
|
||||||
|
|
||||||
|
private volatile ImmutableMap<String, Object> attributes;
|
||||||
|
|
||||||
private volatile String mappingSource;
|
private volatile String mappingSource;
|
||||||
|
|
||||||
private final XContentUidFieldMapper uidFieldMapper;
|
private final XContentUidFieldMapper uidFieldMapper;
|
||||||
@ -166,6 +176,7 @@ public class XContentDocumentMapper implements DocumentMapper, ToXContent {
|
|||||||
private final Object mutex = new Object();
|
private final Object mutex = new Object();
|
||||||
|
|
||||||
public XContentDocumentMapper(XContentObjectMapper rootObjectMapper,
|
public XContentDocumentMapper(XContentObjectMapper rootObjectMapper,
|
||||||
|
ImmutableMap<String, Object> attributes,
|
||||||
XContentUidFieldMapper uidFieldMapper,
|
XContentUidFieldMapper uidFieldMapper,
|
||||||
XContentIdFieldMapper idFieldMapper,
|
XContentIdFieldMapper idFieldMapper,
|
||||||
XContentTypeFieldMapper typeFieldMapper,
|
XContentTypeFieldMapper typeFieldMapper,
|
||||||
@ -175,6 +186,7 @@ public class XContentDocumentMapper implements DocumentMapper, ToXContent {
|
|||||||
@Nullable XContentBoostFieldMapper boostFieldMapper,
|
@Nullable XContentBoostFieldMapper boostFieldMapper,
|
||||||
@Nullable String mappingSource) {
|
@Nullable String mappingSource) {
|
||||||
this.type = rootObjectMapper.name();
|
this.type = rootObjectMapper.name();
|
||||||
|
this.attributes = attributes;
|
||||||
this.mappingSource = mappingSource;
|
this.mappingSource = mappingSource;
|
||||||
this.rootObjectMapper = rootObjectMapper;
|
this.rootObjectMapper = rootObjectMapper;
|
||||||
this.uidFieldMapper = uidFieldMapper;
|
this.uidFieldMapper = uidFieldMapper;
|
||||||
@ -220,6 +232,10 @@ public class XContentDocumentMapper implements DocumentMapper, ToXContent {
|
|||||||
return this.type;
|
return this.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public ImmutableMap<String, Object> attributes() {
|
||||||
|
return this.attributes;
|
||||||
|
}
|
||||||
|
|
||||||
@Override public String mappingSource() {
|
@Override public String mappingSource() {
|
||||||
return this.mappingSource;
|
return this.mappingSource;
|
||||||
}
|
}
|
||||||
@ -367,7 +383,9 @@ public class XContentDocumentMapper implements DocumentMapper, ToXContent {
|
|||||||
MergeContext mergeContext = new MergeContext(this, mergeFlags);
|
MergeContext mergeContext = new MergeContext(this, mergeFlags);
|
||||||
rootObjectMapper.merge(xContentMergeWith.rootObjectMapper, mergeContext);
|
rootObjectMapper.merge(xContentMergeWith.rootObjectMapper, mergeContext);
|
||||||
if (!mergeFlags.simulate()) {
|
if (!mergeFlags.simulate()) {
|
||||||
// update the source to the merged one
|
// let the merge with attributes to override the attributes
|
||||||
|
attributes = mergeWith.attributes();
|
||||||
|
// update the source of the merged one
|
||||||
mappingSource = buildSource();
|
mappingSource = buildSource();
|
||||||
}
|
}
|
||||||
return new MergeResult(mergeContext.buildConflicts());
|
return new MergeResult(mergeContext.buildConflicts());
|
||||||
|
@ -149,6 +149,12 @@ public class XContentDocumentMapperParser implements DocumentMapperParser {
|
|||||||
docBuilder.searchAnalyzer(analysisService.defaultSearchAnalyzer());
|
docBuilder.searchAnalyzer(analysisService.defaultSearchAnalyzer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImmutableMap<String, Object> attributes = ImmutableMap.of();
|
||||||
|
if (rootObj.containsKey("_attributes")) {
|
||||||
|
attributes = ImmutableMap.copyOf((Map<String, Object>) rootObj.get("_attributes"));
|
||||||
|
}
|
||||||
|
docBuilder.attributes(attributes);
|
||||||
|
|
||||||
docBuilder.mappingSource(source);
|
docBuilder.mappingSource(source);
|
||||||
|
|
||||||
XContentDocumentMapper documentMapper = docBuilder.build();
|
XContentDocumentMapper documentMapper = docBuilder.build();
|
||||||
|
@ -78,6 +78,9 @@ public class SimpleXContentMapperTests {
|
|||||||
@Test public void testSimpleParser() throws Exception {
|
@Test public void testSimpleParser() throws Exception {
|
||||||
String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/simple/test-mapping.json");
|
String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/simple/test-mapping.json");
|
||||||
XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(mapping);
|
XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(mapping);
|
||||||
|
|
||||||
|
assertThat((String) docMapper.attributes().get("param1"), equalTo("value1"));
|
||||||
|
|
||||||
byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/xcontent/simple/test1.json");
|
byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/xcontent/simple/test1.json");
|
||||||
Document doc = docMapper.parse(json).doc();
|
Document doc = docMapper.parse(json).doc();
|
||||||
assertThat(doc.get(docMapper.uidMapper().names().indexName()), equalTo(Uid.createUid("person", "1")));
|
assertThat(doc.get(docMapper.uidMapper().names().indexName()), equalTo(Uid.createUid("person", "1")));
|
||||||
|
3
modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/simple/test-mapping.json
3
modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/simple/test-mapping.json
@ -1,5 +1,8 @@
|
|||||||
{
|
{
|
||||||
person : {
|
person : {
|
||||||
|
"_attributes" : {
|
||||||
|
"param1" : "value1"
|
||||||
|
},
|
||||||
date_formats : ["yyyy-MM-dd", "dd-MM-yyyy"],
|
date_formats : ["yyyy-MM-dd", "dd-MM-yyyy"],
|
||||||
dynamic : false,
|
dynamic : false,
|
||||||
enabled : true,
|
enabled : true,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user