Add wildcard support to field resolving in the Get Field Mapping API

Closes #4367
This commit is contained in:
Boaz Leskes 2013-12-06 21:40:54 +01:00
parent a9e259d438
commit 99b421925f
2 changed files with 63 additions and 12 deletions

View File

@ -38,7 +38,7 @@ For which the response is (assuming `text` is a default string field):
The get field mapping API can be used to get the mapping of multiple fields from more than one index or type The get field mapping API can be used to get the mapping of multiple fields from more than one index or type
with a single call. General usage of the API follows the with a single call. General usage of the API follows the
following syntax: `host:port/{index}/{type}/_mapping/field/{field}` where following syntax: `host:port/{index}/{type}/_mapping/field/{field}` where
`{index}`, `{type}` and `{field}` can stand for comma-separated list of names. To `{index}`, `{type}` and `{field}` can stand for comma-separated list of names or wild cards. To
get mappings for all indices you can use `_all` for `{index}`. The get mappings for all indices you can use `_all` for `{index}`. The
following are some examples: following are some examples:
@ -47,12 +47,15 @@ following are some examples:
curl -XGET 'http://localhost:9200/twitter,kimchy/_mapping/field/message' curl -XGET 'http://localhost:9200/twitter,kimchy/_mapping/field/message'
curl -XGET 'http://localhost:9200/_all/tweet,book/_mapping/field/message,user.id' curl -XGET 'http://localhost:9200/_all/tweet,book/_mapping/field/message,user.id'
curl -XGET 'http://localhost:9200/_all/tw*/_mapping/field/*.id'
-------------------------------------------------- --------------------------------------------------
[float] [float]
=== Specifying fields === Specifying fields
The get mapping api allows you to specify fields using any of the following: The get mapping api allows you to specify one or more fields separated with by a comma.
You can also use wildcards. The field names can be any of the following:
[horizontal] [horizontal]
Full names:: the full path, including any parent object name the field is Full names:: the full path, including any parent object name the field is

View File

@ -21,6 +21,7 @@ package org.elasticsearch.action.admin.indices.mapping.get;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Collections2; import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import org.elasticsearch.ElasticSearchException; import org.elasticsearch.ElasticSearchException;
@ -168,22 +169,69 @@ public class TransportGetFieldMappingsAction extends TransportClusterInfoAction<
private ImmutableMap<String, FieldMappingMetaData> findFieldMappingsByType(DocumentMapper documentMapper, String[] fields, private ImmutableMap<String, FieldMappingMetaData> findFieldMappingsByType(DocumentMapper documentMapper, String[] fields,
boolean includeDefaults) throws ElasticSearchException { boolean includeDefaults) throws ElasticSearchException {
MapBuilder<String, FieldMappingMetaData> fieldMappings = new MapBuilder<String, FieldMappingMetaData>(); MapBuilder<String, FieldMappingMetaData> fieldMappings = new MapBuilder<String, FieldMappingMetaData>();
ImmutableList<FieldMapper> allFieldMappers = documentMapper.mappers().mappers();
for (String field : fields) { for (String field : fields) {
FieldMapper fieldMapper = documentMapper.mappers().smartNameFieldMapper(field); if (Regex.isMatchAllPattern(field)) {
if (fieldMapper != null) { for (FieldMapper fieldMapper : allFieldMappers) {
try { addFieldMapper(fieldMapper.names().fullName(), fieldMapper, fieldMappings, includeDefaults);
XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); }
builder.startObject(); } else if (Regex.isSimpleMatchPattern(field)) {
fieldMapper.toXContent(builder, includeDefaults ? includeDefaultsParams : ToXContent.EMPTY_PARAMS); // go through the field mappers 3 times, to make sure we give preference to the resolve order: full name, index name, name.
builder.endObject(); // also make sure we only store each mapper once.
fieldMappings.put(field, new FieldMappingMetaData(fieldMapper.names().fullName(), builder.bytes())); boolean[] resolved = new boolean[allFieldMappers.size()];
} catch (IOException e) { for (int i = 0; i < allFieldMappers.size(); i++) {
throw new ElasticSearchException("failed to serialize XContent of field [" + field + "]", e); FieldMapper fieldMapper = allFieldMappers.get(i);
if (Regex.simpleMatch(field, fieldMapper.names().fullName())) {
addFieldMapper(fieldMapper.names().fullName(), fieldMapper, fieldMappings, includeDefaults);
resolved[i] = true;
}
}
for (int i = 0; i < allFieldMappers.size(); i++) {
if (resolved[i]) {
continue;
}
FieldMapper fieldMapper = allFieldMappers.get(i);
if (Regex.simpleMatch(field, fieldMapper.names().indexName())) {
addFieldMapper(fieldMapper.names().indexName(), fieldMapper, fieldMappings, includeDefaults);
resolved[i] = true;
}
}
for (int i = 0; i < allFieldMappers.size(); i++) {
if (resolved[i]) {
continue;
}
FieldMapper fieldMapper = allFieldMappers.get(i);
if (Regex.simpleMatch(field, fieldMapper.names().name())) {
addFieldMapper(fieldMapper.names().name(), fieldMapper, fieldMappings, includeDefaults);
resolved[i] = true;
}
}
} else {
// not a pattern
FieldMapper fieldMapper = documentMapper.mappers().smartNameFieldMapper(field);
if (fieldMapper != null) {
addFieldMapper(field, fieldMapper, fieldMappings, includeDefaults);
} }
} }
} }
return fieldMappings.immutableMap(); return fieldMappings.immutableMap();
} }
private void addFieldMapper(String field, FieldMapper fieldMapper, MapBuilder<String, FieldMappingMetaData> fieldMappings, boolean includeDefaults) {
if (fieldMappings.containsKey(field)) {
return;
}
try {
XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON);
builder.startObject();
fieldMapper.toXContent(builder, includeDefaults ? includeDefaultsParams : ToXContent.EMPTY_PARAMS);
builder.endObject();
fieldMappings.put(field, new FieldMappingMetaData(fieldMapper.names().fullName(), builder.bytes()));
} catch (IOException e) {
throw new ElasticSearchException("failed to serialize XContent of field [" + field + "]", e);
}
}
} }