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:
kimchy 2010-06-28 09:10:08 +03:00
parent 3770924300
commit cb9be9973b
7 changed files with 47 additions and 14 deletions

View File

@ -226,7 +226,7 @@ public class MetaDataService extends AbstractComponent {
.initializeEmpty(newMetaData.index(index));
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());
return newClusterStateBuilder().state(currentState).routingTable(newRoutingTable).metaData(newMetaData).build();
}
@ -265,7 +265,7 @@ public class MetaDataService extends AbstractComponent {
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());
NodeIndexDeletedAction.Listener listener = new NodeIndexDeletedAction.Listener() {
@ -320,9 +320,9 @@ public class MetaDataService extends AbstractComponent {
// build the updated mapping source
final String updatedMappingSource = existingMapper.buildSource();
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()) {
logger.info("index [" + index + "]: Update mapping [" + type + "] (dynamic)");
logger.info("[{}] update mapping [{}] (dynamic)", index, type);
}
// publish the new mapping
clusterService.submitStateUpdateTask("update-mapping [" + index + "][" + type + "]", new ClusterStateUpdateTask() {
@ -396,9 +396,9 @@ public class MetaDataService extends AbstractComponent {
}
mappings.put(index, mapping);
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()) {
logger.info("index [" + index + "]: Put mapping [" + mapping.v1() + "]");
logger.info("[{}] put_mapping [{}]", index, mapping.v1());
}
}

View File

@ -21,6 +21,7 @@ package org.elasticsearch.index.mapper;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Fieldable;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.util.concurrent.ThreadSafe;
import javax.annotation.Nullable;
@ -39,6 +40,11 @@ public interface DocumentMapper {
*/
String mappingSource();
/**
* Attributes of this type mappings.
*/
ImmutableMap<String, Object> attributes();
/**
* Generates the source of the mapper based on the current mappings.
*/

View File

@ -46,7 +46,7 @@ import java.net.URL;
import static org.elasticsearch.common.collect.MapBuilder.*;
/**
* @author kimchy (Shay Banon)
* @author kimchy (shay.banon)
*/
@ThreadSafe
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 ClassLoader indexClassLoader;
private final String dynamicMappingSource;
private volatile ImmutableMap<String, DocumentMapper> mappers = ImmutableMap.of();
@ -87,7 +85,6 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
super(index, indexSettings);
this.documentParser = new XContentDocumentMapperParser(analysisService);
this.searchAnalyzer = new SmartIndexNameSearchAnalyzer(analysisService.defaultSearchAnalyzer());
this.indexClassLoader = indexSettings.getClassLoader();
this.dynamic = componentSettings.getAsBoolean("dynamic", true);
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");
} catch (FailedToResolveConfigException e) {
// 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 {
try {
@ -127,7 +124,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
} else {
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() {

View File

@ -22,6 +22,7 @@ package org.elasticsearch.index.mapper.xcontent;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.elasticsearch.common.Preconditions;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.thread.ThreadLocals;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentFactory;
@ -64,12 +65,19 @@ public class XContentDocumentMapper implements DocumentMapper, ToXContent {
private String mappingSource;
private ImmutableMap<String, Object> attributes = ImmutableMap.of();
private XContentMapper.BuilderContext builderContext = new XContentMapper.BuilderContext(new ContentPath(1));
public Builder(XContentObjectMapper.Builder builder) {
this.rootObjectMapper = builder.build(builderContext);
}
public Builder attributes(ImmutableMap<String, Object> attributes) {
this.attributes = attributes;
return this;
}
public Builder sourceField(XContentSourceFieldMapper.Builder builder) {
this.sourceFieldMapper = builder.build(builderContext);
return this;
@ -125,7 +133,7 @@ public class XContentDocumentMapper implements DocumentMapper, ToXContent {
public XContentDocumentMapper build() {
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);
}
}
@ -139,6 +147,8 @@ public class XContentDocumentMapper implements DocumentMapper, ToXContent {
private final String type;
private volatile ImmutableMap<String, Object> attributes;
private volatile String mappingSource;
private final XContentUidFieldMapper uidFieldMapper;
@ -166,6 +176,7 @@ public class XContentDocumentMapper implements DocumentMapper, ToXContent {
private final Object mutex = new Object();
public XContentDocumentMapper(XContentObjectMapper rootObjectMapper,
ImmutableMap<String, Object> attributes,
XContentUidFieldMapper uidFieldMapper,
XContentIdFieldMapper idFieldMapper,
XContentTypeFieldMapper typeFieldMapper,
@ -175,6 +186,7 @@ public class XContentDocumentMapper implements DocumentMapper, ToXContent {
@Nullable XContentBoostFieldMapper boostFieldMapper,
@Nullable String mappingSource) {
this.type = rootObjectMapper.name();
this.attributes = attributes;
this.mappingSource = mappingSource;
this.rootObjectMapper = rootObjectMapper;
this.uidFieldMapper = uidFieldMapper;
@ -220,6 +232,10 @@ public class XContentDocumentMapper implements DocumentMapper, ToXContent {
return this.type;
}
@Override public ImmutableMap<String, Object> attributes() {
return this.attributes;
}
@Override public String mappingSource() {
return this.mappingSource;
}
@ -367,7 +383,9 @@ public class XContentDocumentMapper implements DocumentMapper, ToXContent {
MergeContext mergeContext = new MergeContext(this, mergeFlags);
rootObjectMapper.merge(xContentMergeWith.rootObjectMapper, mergeContext);
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();
}
return new MergeResult(mergeContext.buildConflicts());

View File

@ -149,6 +149,12 @@ public class XContentDocumentMapperParser implements DocumentMapperParser {
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);
XContentDocumentMapper documentMapper = docBuilder.build();

View File

@ -78,6 +78,9 @@ public class SimpleXContentMapperTests {
@Test public void testSimpleParser() throws Exception {
String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/simple/test-mapping.json");
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");
Document doc = docMapper.parse(json).doc();
assertThat(doc.get(docMapper.uidMapper().names().indexName()), equalTo(Uid.createUid("person", "1")));

View File

@ -1,5 +1,8 @@
{
person : {
"_attributes" : {
"param1" : "value1"
},
date_formats : ["yyyy-MM-dd", "dd-MM-yyyy"],
dynamic : false,
enabled : true,