add path support for id field, fix issue 1245

This commit is contained in:
Benjamin Devèze 2011-08-30 18:56:20 +02:00 committed by Shay Banon
parent 2d1a645231
commit d1d3340aa2
7 changed files with 260 additions and 60 deletions

View File

@ -35,7 +35,6 @@ import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.routing.GroupShardsIterator;
import org.elasticsearch.cluster.routing.ShardIterator;
import org.elasticsearch.common.UUID;
import org.elasticsearch.common.collect.Lists;
import org.elasticsearch.common.collect.Maps;
import org.elasticsearch.common.collect.Sets;
@ -139,14 +138,6 @@ public class TransportBulkAction extends BaseAction<BulkRequest, BulkResponse> {
for (ActionRequest request : bulkRequest.requests) {
if (request instanceof IndexRequest) {
IndexRequest indexRequest = (IndexRequest) request;
if (allowIdGeneration) {
if (indexRequest.id() == null) {
indexRequest.id(UUID.randomBase64UUID());
// since we generate the id, change it to CREATE
indexRequest.opType(IndexRequest.OpType.CREATE);
}
}
String aliasOrIndex = indexRequest.index();
indexRequest.index(clusterState.metaData().concreteIndex(indexRequest.index()));
@ -154,7 +145,7 @@ public class TransportBulkAction extends BaseAction<BulkRequest, BulkResponse> {
if (metaData.hasIndex(indexRequest.index())) {
mappingMd = metaData.index(indexRequest.index()).mapping(indexRequest.type());
}
indexRequest.process(metaData, aliasOrIndex, mappingMd);
indexRequest.process(metaData, aliasOrIndex, mappingMd, allowIdGeneration);
} else if (request instanceof DeleteRequest) {
DeleteRequest deleteRequest = (DeleteRequest) request;
deleteRequest.index(clusterState.metaData().concreteIndex(deleteRequest.index()));

View File

@ -34,6 +34,7 @@ import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.Required;
import org.elasticsearch.common.UUID;
import org.elasticsearch.common.Unicode;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
@ -577,7 +578,7 @@ public class IndexRequest extends ShardReplicationOperationRequest {
return this.percolate;
}
public void process(MetaData metaData, String aliasOrIndex, @Nullable MappingMetaData mappingMd) throws ElasticSearchException {
public void process(MetaData metaData, String aliasOrIndex, @Nullable MappingMetaData mappingMd, boolean allowIdGeneration) throws ElasticSearchException {
// resolve the routing if needed
routing(metaData.resolveIndexRouting(routing, aliasOrIndex));
// resolve timestamp if provided externally
@ -587,13 +588,16 @@ public class IndexRequest extends ShardReplicationOperationRequest {
}
// extract values if needed
if (mappingMd != null) {
MappingMetaData.ParseContext parseContext = mappingMd.createParseContext(routing, timestamp);
MappingMetaData.ParseContext parseContext = mappingMd.createParseContext(id, routing, timestamp);
if (parseContext.shouldParse()) {
XContentParser parser = null;
try {
parser = XContentFactory.xContent(source, sourceOffset, sourceLength).createParser(source, sourceOffset, sourceLength);
mappingMd.parse(parser, parseContext);
if (parseContext.shouldParseId()) {
id = parseContext.id();
}
if (parseContext.shouldParseRouting()) {
routing = parseContext.routing();
}
@ -609,11 +613,22 @@ public class IndexRequest extends ShardReplicationOperationRequest {
}
}
}
// might as well check for routing here
if (mappingMd.routing().required() && routing == null) {
throw new RoutingMissingException(index, type, id);
}
}
// generate id if not already provided and id generation is allowed
if (allowIdGeneration) {
if (id == null) {
id(UUID.randomBase64UUID());
// since we generate the id, change it to CREATE
opType(IndexRequest.OpType.CREATE);
}
}
// generate timestamp if not provided, we always have one post this stage...
if (timestamp == null) {
timestamp = String.valueOf(System.currentTimeMillis());

View File

@ -36,7 +36,6 @@ import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.routing.ShardIterator;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.UUID;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.engine.Engine;
@ -117,14 +116,6 @@ public class TransportIndexAction extends TransportShardReplicationOperationActi
}
private void innerExecute(final IndexRequest request, final ActionListener<IndexResponse> listener) {
if (allowIdGeneration) {
if (request.id() == null) {
request.id(UUID.randomBase64UUID());
// since we generate the id, change it to CREATE
request.opType(IndexRequest.OpType.CREATE);
}
}
MetaData metaData = clusterService.state().metaData();
String aliasOrIndex = request.index();
request.index(metaData.concreteIndex(request.index()));
@ -132,7 +123,8 @@ public class TransportIndexAction extends TransportShardReplicationOperationActi
if (metaData.hasIndex(request.index())) {
mappingMd = metaData.index(request.index()).mapping(request.type());
}
request.process(metaData, aliasOrIndex, mappingMd);
request.process(metaData, aliasOrIndex, mappingMd, allowIdGeneration);
super.doExecute(request, listener);
}

View File

@ -42,6 +42,36 @@ import static org.elasticsearch.common.xcontent.support.XContentMapValues.*;
*/
public class MappingMetaData {
public static class Id {
public static final Id EMPTY = new Id(null);
private final String path;
private final String[] pathElements;
public Id(String path) {
this.path = path;
if (path == null) {
pathElements = Strings.EMPTY_ARRAY;
} else {
pathElements = Strings.delimitedListToStringArray(path, ".");
}
}
public boolean hasPath() {
return path != null;
}
public String path() {
return this.path;
}
public String[] pathElements() {
return this.pathElements;
}
}
public static class Routing {
public static final Routing EMPTY = new Routing(false, null);
@ -149,12 +179,14 @@ public class MappingMetaData {
private final CompressedString source;
private final Id id;
private final Routing routing;
private final Timestamp timestamp;
public MappingMetaData(DocumentMapper docMapper) {
this.type = docMapper.type();
this.source = docMapper.mappingSource();
this.id = new Id(docMapper.idFieldMapper().path());
this.routing = new Routing(docMapper.routingFieldMapper().required(), docMapper.routingFieldMapper().path());
this.timestamp = new Timestamp(docMapper.timestampFieldMapper().enabled(), docMapper.timestampFieldMapper().path(), docMapper.timestampFieldMapper().dateTimeFormatter().format());
}
@ -166,6 +198,20 @@ public class MappingMetaData {
if (mapping.size() == 1 && mapping.containsKey(type)) {
withoutType = (Map<String, Object>) mapping.get(type);
}
if (withoutType.containsKey("_id")) {
String path = null;
Map<String, Object> routingNode = (Map<String, Object>) withoutType.get("_id");
for (Map.Entry<String, Object> entry : routingNode.entrySet()) {
String fieldName = Strings.toUnderscoreCase(entry.getKey());
Object fieldNode = entry.getValue();
if (fieldName.equals("path")) {
path = fieldNode.toString();
}
}
this.id = new Id(path);
} else {
this.id = Id.EMPTY;
}
if (withoutType.containsKey("_routing")) {
boolean required = false;
String path = null;
@ -205,9 +251,10 @@ public class MappingMetaData {
}
}
MappingMetaData(String type, CompressedString source, Routing routing, Timestamp timestamp) {
MappingMetaData(String type, CompressedString source, Id id, Routing routing, Timestamp timestamp) {
this.type = type;
this.source = source;
this.id = id;
this.routing = routing;
this.timestamp = timestamp;
}
@ -220,6 +267,10 @@ public class MappingMetaData {
return this.source;
}
public Id id() {
return this.id;
}
public Routing routing() {
return this.routing;
}
@ -228,8 +279,9 @@ public class MappingMetaData {
return this.timestamp;
}
public ParseContext createParseContext(@Nullable String routing, @Nullable String timestamp) {
public ParseContext createParseContext(@Nullable String id, @Nullable String routing, @Nullable String timestamp) {
return new ParseContext(
id == null && id().hasPath(),
routing == null && routing().hasPath(),
timestamp == null && timestamp().hasPath()
);
@ -251,6 +303,7 @@ public class MappingMetaData {
if (t == XContentParser.Token.START_OBJECT) {
t = parser.nextToken();
}
String idPart = context.idParsingStillNeeded() ? id().pathElements()[context.locationId] : null;
String routingPart = context.routingParsingStillNeeded() ? routing().pathElements()[context.locationRouting] : null;
String timestampPart = context.timestampParsingStillNeeded() ? timestamp().pathElements()[context.locationTimestamp] : null;
@ -259,9 +312,17 @@ public class MappingMetaData {
String fieldName = parser.currentName();
// And then the value...
t = parser.nextToken();
boolean incLocationId = false;
boolean incLocationRouting = false;
boolean incLocationTimestamp = false;
if (context.idParsingStillNeeded() && fieldName.equals(idPart)) {
if (context.locationId + 1 == id.pathElements().length) {
context.id = parser.textOrNull();
context.idResolved = true;
} else {
incLocationId = true;
}
}
if (context.routingParsingStillNeeded() && fieldName.equals(routingPart)) {
if (context.locationRouting + 1 == routing.pathElements().length) {
context.routing = parser.textOrNull();
@ -279,11 +340,13 @@ public class MappingMetaData {
}
}
if (incLocationRouting || incLocationTimestamp) {
if (incLocationId || incLocationRouting || incLocationTimestamp) {
if (t == XContentParser.Token.START_OBJECT) {
context.locationId += incLocationId ? 1 : 0;
context.locationRouting += incLocationRouting ? 1 : 0;
context.locationTimestamp += incLocationTimestamp ? 1 : 0;
innerParse(parser, context);
context.locationId -= incLocationId ? 1 : 0;
context.locationRouting -= incLocationRouting ? 1 : 0;
context.locationTimestamp -= incLocationTimestamp ? 1 : 0;
}
@ -300,6 +363,13 @@ public class MappingMetaData {
public static void writeTo(MappingMetaData mappingMd, StreamOutput out) throws IOException {
out.writeUTF(mappingMd.type());
mappingMd.source().writeTo(out);
// id
if (mappingMd.id().hasPath()) {
out.writeBoolean(true);
out.writeUTF(mappingMd.id().path());
} else {
out.writeBoolean(false);
}
// routing
out.writeBoolean(mappingMd.routing().required());
if (mappingMd.routing().hasPath()) {
@ -322,11 +392,13 @@ public class MappingMetaData {
public static MappingMetaData readFrom(StreamInput in) throws IOException {
String type = in.readUTF();
CompressedString source = CompressedString.readCompressedString(in);
// id
Id id = new Id(in.readBoolean() ? in.readUTF() : null);
// routing
Routing routing = new Routing(in.readBoolean(), in.readBoolean() ? in.readUTF() : null);
// timestamp
Timestamp timestamp = new Timestamp(in.readBoolean(), in.readBoolean() ? in.readUTF() : null, in.readUTF());
return new MappingMetaData(type, source, routing, timestamp);
return new MappingMetaData(type, source, id, routing, timestamp);
}
public static class ParseResult {
@ -344,22 +416,54 @@ public class MappingMetaData {
}
public static class ParseContext {
final boolean shouldParseId;
final boolean shouldParseRouting;
final boolean shouldParseTimestamp;
int locationId = 0;
int locationRouting = 0;
int locationTimestamp = 0;
boolean idResolved;
boolean routingResolved;
boolean timestampResolved;
String id;
String routing;
String timestamp;
public ParseContext(boolean shouldParseRouting, boolean shouldParseTimestamp) {
public ParseContext(boolean shouldParseId, boolean shouldParseRouting, boolean shouldParseTimestamp) {
this.shouldParseId = shouldParseId;
this.shouldParseRouting = shouldParseRouting;
this.shouldParseTimestamp = shouldParseTimestamp;
}
/**
* The id value parsed, <tt>null</tt> if does not require parsing, or not resolved.
*/
public String id() {
return id;
}
/**
* Does id parsing really needed at all?
*/
public boolean shouldParseId() {
return shouldParseId;
}
/**
* Has id been resolved during the parsing phase.
*/
public boolean idResolved() {
return idResolved;
}
/**
* Is id parsing still needed?
*/
public boolean idParsingStillNeeded() {
return shouldParseId && !idResolved;
}
/**
* The routing value parsed, <tt>null</tt> if does not require parsing, or not resolved.
*/
@ -420,14 +524,14 @@ public class MappingMetaData {
* Do we really need parsing?
*/
public boolean shouldParse() {
return shouldParseRouting || shouldParseTimestamp;
return shouldParseId || shouldParseRouting || shouldParseTimestamp;
}
/**
* Is parsing still needed?
*/
public boolean parsingStillNeeded() {
return routingParsingStillNeeded() || timestampParsingStillNeeded();
return idParsingStillNeeded() || routingParsingStillNeeded() || timestampParsingStillNeeded();
}
}
}

View File

@ -352,6 +352,10 @@ public class DocumentMapper implements ToXContent {
return rootMapper(AllFieldMapper.class);
}
public IdFieldMapper idFieldMapper() {
return rootMapper(IdFieldMapper.class);
}
public RoutingFieldMapper routingFieldMapper() {
return rootMapper(RoutingFieldMapper.class);
}

View File

@ -22,6 +22,7 @@ package org.elasticsearch.index.mapper.internal;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
@ -56,10 +57,13 @@ public class IdFieldMapper extends AbstractFieldMapper<String> implements Intern
public static final Field.Store STORE = Field.Store.NO;
public static final boolean OMIT_NORMS = true;
public static final boolean OMIT_TERM_FREQ_AND_POSITIONS = true;
public static final String PATH = null;
}
public static class Builder extends AbstractFieldMapper.Builder<Builder, IdFieldMapper> {
private String path = Defaults.PATH;
public Builder() {
super(Defaults.NAME);
indexName = Defaults.INDEX_NAME;
@ -69,8 +73,13 @@ public class IdFieldMapper extends AbstractFieldMapper<String> implements Intern
omitTermFreqAndPositions = Defaults.OMIT_TERM_FREQ_AND_POSITIONS;
}
public Builder path(String path) {
this.path = path;
return builder;
}
@Override public IdFieldMapper build(BuilderContext context) {
return new IdFieldMapper(name, indexName, index, store, termVector, boost, omitNorms, omitTermFreqAndPositions);
return new IdFieldMapper(name, indexName, index, store, termVector, boost, omitNorms, omitTermFreqAndPositions, path);
}
}
@ -78,10 +87,19 @@ public class IdFieldMapper extends AbstractFieldMapper<String> implements Intern
@Override public Mapper.Builder parse(String name, Map<String, Object> node, ParserContext parserContext) throws MapperParsingException {
IdFieldMapper.Builder builder = id();
parseField(builder, builder.name, node, parserContext);
for (Map.Entry<String, Object> entry : node.entrySet()) {
String fieldName = Strings.toUnderscoreCase(entry.getKey());
Object fieldNode = entry.getValue();
if (fieldName.equals("path")) {
builder.path(fieldNode.toString());
}
}
return builder;
}
}
private final String path;
public IdFieldMapper() {
this(Defaults.NAME, Defaults.INDEX_NAME, Defaults.INDEX);
}
@ -92,13 +110,18 @@ public class IdFieldMapper extends AbstractFieldMapper<String> implements Intern
protected IdFieldMapper(String name, String indexName, Field.Index index) {
this(name, indexName, index, Defaults.STORE, Defaults.TERM_VECTOR, Defaults.BOOST,
Defaults.OMIT_NORMS, Defaults.OMIT_TERM_FREQ_AND_POSITIONS);
Defaults.OMIT_NORMS, Defaults.OMIT_TERM_FREQ_AND_POSITIONS, Defaults.PATH);
}
protected IdFieldMapper(String name, String indexName, Field.Index index, Field.Store store, Field.TermVector termVector,
float boost, boolean omitNorms, boolean omitTermFreqAndPositions) {
float boost, boolean omitNorms, boolean omitTermFreqAndPositions, String path) {
super(new Names(name, indexName, indexName, name), index, store, termVector, boost, omitNorms, omitTermFreqAndPositions,
Lucene.KEYWORD_ANALYZER, Lucene.KEYWORD_ANALYZER);
this.path = path;
}
public String path() {
return this.path;
}
public String value(Document document) {

View File

@ -30,14 +30,34 @@ import static org.hamcrest.Matchers.*;
@Test
public class MappingMetaDataParserTests {
@Test public void testParseRoutingAlone() throws Exception {
@Test public void testParseIdAlone() throws Exception {
MappingMetaData md = new MappingMetaData("type1", new CompressedString(""),
new MappingMetaData.Id("id"),
new MappingMetaData.Routing(true, "routing"),
new MappingMetaData.Timestamp(true, "timestamp", "dateOptionalTime"));
byte[] bytes = jsonBuilder().startObject().field("field1", "value1").field("field2", "value2")
.field("routing", "routing_value").field("timestamp", "1").endObject().copiedBytes();
MappingMetaData.ParseContext parseContext = md.createParseContext(null, "1");
.field("id", "id").field("routing", "routing_value").field("timestamp", "1").endObject().copiedBytes();
MappingMetaData.ParseContext parseContext = md.createParseContext(null, "routing_value", "1");
md.parse(XContentFactory.xContent(bytes).createParser(bytes), parseContext);
assertThat(parseContext.id(), equalTo("id"));
assertThat(parseContext.idResolved(), equalTo(true));
assertThat(parseContext.routing(), nullValue());
assertThat(parseContext.routingResolved(), equalTo(false));
assertThat(parseContext.timestamp(), nullValue());
assertThat(parseContext.timestampResolved(), equalTo(false));
}
@Test public void testParseRoutingAlone() throws Exception {
MappingMetaData md = new MappingMetaData("type1", new CompressedString(""),
new MappingMetaData.Id("id"),
new MappingMetaData.Routing(true, "routing"),
new MappingMetaData.Timestamp(true, "timestamp", "dateOptionalTime"));
byte[] bytes = jsonBuilder().startObject().field("field1", "value1").field("field2", "value2")
.field("id", "id").field("routing", "routing_value").field("timestamp", "1").endObject().copiedBytes();
MappingMetaData.ParseContext parseContext = md.createParseContext("id", null, "1");
md.parse(XContentFactory.xContent(bytes).createParser(bytes), parseContext);
assertThat(parseContext.id(), nullValue());
assertThat(parseContext.idResolved(), equalTo(false));
assertThat(parseContext.routing(), equalTo("routing_value"));
assertThat(parseContext.routingResolved(), equalTo(true));
assertThat(parseContext.timestamp(), nullValue());
@ -46,54 +66,86 @@ public class MappingMetaDataParserTests {
@Test public void testParseTimestampAlone() throws Exception {
MappingMetaData md = new MappingMetaData("type1", new CompressedString(""),
new MappingMetaData.Id("id"),
new MappingMetaData.Routing(true, "routing"),
new MappingMetaData.Timestamp(true, "timestamp", "dateOptionalTime"));
byte[] bytes = jsonBuilder().startObject().field("field1", "value1").field("field2", "value2")
.field("routing", "routing_value").field("timestamp", "1").endObject().copiedBytes();
MappingMetaData.ParseContext parseContext = md.createParseContext("routing_value1", null);
.field("id", "id").field("routing", "routing_value").field("timestamp", "1").endObject().copiedBytes();
MappingMetaData.ParseContext parseContext = md.createParseContext("id", "routing_value1", null);
md.parse(XContentFactory.xContent(bytes).createParser(bytes), parseContext);
assertThat(parseContext.id(), nullValue());
assertThat(parseContext.idResolved(), equalTo(false));
assertThat(parseContext.routing(), nullValue());
assertThat(parseContext.routingResolved(), equalTo(false));
assertThat(parseContext.timestamp(), equalTo("1"));
assertThat(parseContext.timestampResolved(), equalTo(true));
}
@Test public void testParseRoutingAndTimestamp() throws Exception {
@Test public void testParseIdAndRoutingAndTimestamp() throws Exception {
MappingMetaData md = new MappingMetaData("type1", new CompressedString(""),
new MappingMetaData.Id("id"),
new MappingMetaData.Routing(true, "routing"),
new MappingMetaData.Timestamp(true, "timestamp", "dateOptionalTime"));
byte[] bytes = jsonBuilder().startObject().field("field1", "value1").field("field2", "value2")
.field("routing", "routing_value").field("timestamp", "1").endObject().copiedBytes();
MappingMetaData.ParseContext parseContext = md.createParseContext(null, null);
.field("id", "id").field("routing", "routing_value").field("timestamp", "1").endObject().copiedBytes();
MappingMetaData.ParseContext parseContext = md.createParseContext(null, null, null);
md.parse(XContentFactory.xContent(bytes).createParser(bytes), parseContext);
assertThat(parseContext.id(), equalTo("id"));
assertThat(parseContext.routing(), equalTo("routing_value"));
assertThat(parseContext.timestamp(), equalTo("1"));
}
@Test public void testParseRoutingAndTimestampWithPath() throws Exception {
@Test public void testParseIdAndRoutingAndTimestampWithPath() throws Exception {
MappingMetaData md = new MappingMetaData("type1", new CompressedString(""),
new MappingMetaData.Id("obj1.id"),
new MappingMetaData.Routing(true, "obj1.routing"),
new MappingMetaData.Timestamp(true, "obj2.timestamp", "dateOptionalTime"));
byte[] bytes = jsonBuilder().startObject().field("field1", "value1").field("field2", "value2")
.startObject("obj0").field("field1", "value1").field("field2", "value2").endObject()
.startObject("obj1").field("routing", "routing_value").endObject()
.startObject("obj1").field("id", "id").field("routing", "routing_value").endObject()
.startObject("obj2").field("timestamp", "1").endObject()
.endObject().copiedBytes();
MappingMetaData.ParseContext parseContext = md.createParseContext(null, null);
MappingMetaData.ParseContext parseContext = md.createParseContext(null, null, null);
md.parse(XContentFactory.xContent(bytes).createParser(bytes), parseContext);
assertThat(parseContext.id(), equalTo("id"));
assertThat(parseContext.routing(), equalTo("routing_value"));
assertThat(parseContext.timestamp(), equalTo("1"));
}
@Test public void testParseIdWithPath() throws Exception {
MappingMetaData md = new MappingMetaData("type1", new CompressedString(""),
new MappingMetaData.Id("obj1.id"),
new MappingMetaData.Routing(true, "obj1.routing"),
new MappingMetaData.Timestamp(true, "obj2.timestamp", "dateOptionalTime"));
byte[] bytes = jsonBuilder().startObject().field("field1", "value1").field("field2", "value2")
.startObject("obj0").field("field1", "value1").field("field2", "value2").endObject()
.startObject("obj1").field("id", "id").field("routing", "routing_value").endObject()
.startObject("obj2").field("timestamp", "1").endObject()
.endObject().copiedBytes();
MappingMetaData.ParseContext parseContext = md.createParseContext(null, "routing_value", "2");
md.parse(XContentFactory.xContent(bytes).createParser(bytes), parseContext);
assertThat(parseContext.id(), equalTo("id"));
assertThat(parseContext.idResolved(), equalTo(true));
assertThat(parseContext.routing(), nullValue());
assertThat(parseContext.routingResolved(), equalTo(false));
assertThat(parseContext.timestamp(), nullValue());
assertThat(parseContext.timestampResolved(), equalTo(false));
}
@Test public void testParseRoutingWithPath() throws Exception {
MappingMetaData md = new MappingMetaData("type1", new CompressedString(""),
new MappingMetaData.Id("obj1.id"),
new MappingMetaData.Routing(true, "obj1.routing"),
new MappingMetaData.Timestamp(true, "obj2.timestamp", "dateOptionalTime"));
byte[] bytes = jsonBuilder().startObject().field("field1", "value1").field("field2", "value2")
.startObject("obj0").field("field1", "value1").field("field2", "value2").endObject()
.startObject("obj1").field("routing", "routing_value").endObject()
.startObject("obj1").field("id", "id").field("routing", "routing_value").endObject()
.startObject("obj2").field("timestamp", "1").endObject()
.endObject().copiedBytes();
MappingMetaData.ParseContext parseContext = md.createParseContext(null, "2");
MappingMetaData.ParseContext parseContext = md.createParseContext("id", null, "2");
md.parse(XContentFactory.xContent(bytes).createParser(bytes), parseContext);
assertThat(parseContext.id(), nullValue());
assertThat(parseContext.idResolved(), equalTo(false));
assertThat(parseContext.routing(), equalTo("routing_value"));
assertThat(parseContext.routingResolved(), equalTo(true));
assertThat(parseContext.timestamp(), nullValue());
@ -102,6 +154,7 @@ public class MappingMetaDataParserTests {
@Test public void testParseTimestampWithPath() throws Exception {
MappingMetaData md = new MappingMetaData("type1", new CompressedString(""),
new MappingMetaData.Id("obj1.id"),
new MappingMetaData.Routing(true, "obj1.routing"),
new MappingMetaData.Timestamp(true, "obj2.timestamp", "dateOptionalTime"));
byte[] bytes = jsonBuilder().startObject().field("field1", "value1").field("field2", "value2")
@ -109,36 +162,44 @@ public class MappingMetaDataParserTests {
.startObject("obj1").field("routing", "routing_value").endObject()
.startObject("obj2").field("timestamp", "1").endObject()
.endObject().copiedBytes();
MappingMetaData.ParseContext parseContext = md.createParseContext("routing_value1", null);
MappingMetaData.ParseContext parseContext = md.createParseContext(null, "routing_value1", null);
md.parse(XContentFactory.xContent(bytes).createParser(bytes), parseContext);
assertThat(parseContext.id(), nullValue());
assertThat(parseContext.idResolved(), equalTo(false));
assertThat(parseContext.routing(), nullValue());
assertThat(parseContext.routingResolved(), equalTo(false));
assertThat(parseContext.timestamp(), equalTo("1"));
assertThat(parseContext.timestampResolved(), equalTo(true));
}
@Test public void testParseRoutingAndTimestampWithinSamePath() throws Exception {
@Test public void testParseIdAndRoutingAndTimestampWithinSamePath() throws Exception {
MappingMetaData md = new MappingMetaData("type1", new CompressedString(""),
new MappingMetaData.Id("obj1.id"),
new MappingMetaData.Routing(true, "obj1.routing"),
new MappingMetaData.Timestamp(true, "obj1.timestamp", "dateOptionalTime"));
byte[] bytes = jsonBuilder().startObject().field("field1", "value1").field("field2", "value2")
.startObject("obj0").field("field1", "value1").field("field2", "value2").endObject()
.startObject("obj1").field("routing", "routing_value").field("timestamp", "1").endObject()
.startObject("obj1").field("id", "id").field("routing", "routing_value").field("timestamp", "1").endObject()
.startObject("obj2").field("field1", "value1").endObject()
.endObject().copiedBytes();
MappingMetaData.ParseContext parseContext = md.createParseContext(null, null);
MappingMetaData.ParseContext parseContext = md.createParseContext(null, null, null);
md.parse(XContentFactory.xContent(bytes).createParser(bytes), parseContext);
assertThat(parseContext.id(), equalTo("id"));
assertThat(parseContext.routing(), equalTo("routing_value"));
assertThat(parseContext.timestamp(), equalTo("1"));
}
@Test public void testParseRoutingAndTimestampWithinSamePathAndMoreLevels() throws Exception {
@Test public void testParseIdAndRoutingAndTimestampWithinSamePathAndMoreLevels() throws Exception {
MappingMetaData md = new MappingMetaData("type1", new CompressedString(""),
new MappingMetaData.Id("obj1.obj0.id"),
new MappingMetaData.Routing(true, "obj1.obj2.routing"),
new MappingMetaData.Timestamp(true, "obj1.obj3.timestamp", "dateOptionalTime"));
byte[] bytes = jsonBuilder().startObject().field("field1", "value1").field("field2", "value2")
.startObject("obj0").field("field1", "value1").field("field2", "value2").endObject()
.startObject("obj1")
.startObject("obj0")
.field("id", "id")
.endObject()
.startObject("obj2")
.field("routing", "routing_value")
.endObject()
@ -148,31 +209,36 @@ public class MappingMetaDataParserTests {
.endObject()
.startObject("obj2").field("field1", "value1").endObject()
.endObject().copiedBytes();
MappingMetaData.ParseContext parseContext = md.createParseContext(null, null);
MappingMetaData.ParseContext parseContext = md.createParseContext(null, null, null);
md.parse(XContentFactory.xContent(bytes).createParser(bytes), parseContext);
assertThat(parseContext.id(), equalTo("id"));
assertThat(parseContext.routing(), equalTo("routing_value"));
assertThat(parseContext.timestamp(), equalTo("1"));
}
@Test public void testParseRoutingAndTimestampWithSameRepeatedObject() throws Exception {
@Test public void testParseIdAndRoutingAndTimestampWithSameRepeatedObject() throws Exception {
MappingMetaData md = new MappingMetaData("type1", new CompressedString(""),
new MappingMetaData.Id("obj1.id"),
new MappingMetaData.Routing(true, "obj1.routing"),
new MappingMetaData.Timestamp(true, "obj1.timestamp", "dateOptionalTime"));
byte[] bytes = jsonBuilder().startObject().field("field1", "value1").field("field2", "value2")
.startObject("obj0").field("field1", "value1").field("field2", "value2").endObject()
.startObject("obj1").field("id", "id").endObject()
.startObject("obj1").field("routing", "routing_value").endObject()
.startObject("obj1").field("timestamp", "1").endObject()
.endObject().copiedBytes();
MappingMetaData.ParseContext parseContext = md.createParseContext(null, null);
MappingMetaData.ParseContext parseContext = md.createParseContext(null, null, null);
md.parse(XContentFactory.xContent(bytes).createParser(bytes), parseContext);
assertThat(parseContext.id(), equalTo("id"));
assertThat(parseContext.routing(), equalTo("routing_value"));
assertThat(parseContext.timestamp(), equalTo("1"));
}
//
@Test public void testParseRoutingTimestampWithRepeatedField() throws Exception {
@Test public void testParseIdRoutingTimestampWithRepeatedField() throws Exception {
MappingMetaData md = new MappingMetaData("type1", new CompressedString(""),
new MappingMetaData.Id("field1"),
new MappingMetaData.Routing(true, "field1.field1"),
new MappingMetaData.Timestamp(true, "field1", "dateOptionalTime"));
@ -185,14 +251,16 @@ public class MappingMetaDataParserTests {
.field("zzz", "wr")
.endObject().copiedBytes();
MappingMetaData.ParseContext parseContext = md.createParseContext(null, null);
MappingMetaData.ParseContext parseContext = md.createParseContext(null, null, null);
md.parse(XContentFactory.xContent(bytes).createParser(bytes), parseContext);
assertThat(parseContext.id(), equalTo("foo"));
assertThat(parseContext.routing(), nullValue());
assertThat(parseContext.timestamp(), equalTo("foo"));
}
@Test public void testParseRoutingWithRepeatedFieldAndObject() throws Exception {
@Test public void testParseNoIdRoutingWithRepeatedFieldAndObject() throws Exception {
MappingMetaData md = new MappingMetaData("type1", new CompressedString(""),
new MappingMetaData.Id("id"),
new MappingMetaData.Routing(true, "field1.field1.field2"),
new MappingMetaData.Timestamp(true, "field1", "dateOptionalTime"));
@ -205,14 +273,16 @@ public class MappingMetaDataParserTests {
.field("zzz", "wr")
.endObject().copiedBytes();
MappingMetaData.ParseContext parseContext = md.createParseContext(null, null);
MappingMetaData.ParseContext parseContext = md.createParseContext(null, null, null);
md.parse(XContentFactory.xContent(bytes).createParser(bytes), parseContext);
assertThat(parseContext.id(), nullValue());
assertThat(parseContext.routing(), nullValue());
assertThat(parseContext.timestamp(), equalTo("foo"));
}
@Test public void testParseRoutingWithRepeatedFieldAndValidRouting() throws Exception {
MappingMetaData md = new MappingMetaData("type1", new CompressedString(""),
new MappingMetaData.Id(null),
new MappingMetaData.Routing(true, "field1.field2"),
new MappingMetaData.Timestamp(true, "field1", "dateOptionalTime"));
@ -225,8 +295,9 @@ public class MappingMetaDataParserTests {
.field("zzz", "wr")
.endObject().copiedBytes();
MappingMetaData.ParseContext parseContext = md.createParseContext(null, null);
MappingMetaData.ParseContext parseContext = md.createParseContext(null, null, null);
md.parse(XContentFactory.xContent(bytes).createParser(bytes), parseContext);
assertThat(parseContext.id(), nullValue());
assertThat(parseContext.routing(), equalTo("bar"));
assertThat(parseContext.timestamp(), equalTo("foo"));
}