mirror of https://github.com/apache/lucene.git
SOLR-4537: Clean up schema information REST API
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1454141 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
62dcc4274a
commit
14c9f28f57
|
@ -38,6 +38,35 @@ TBD...
|
||||||
Detailed Change List
|
Detailed Change List
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
================== 4.3.0 ==================
|
||||||
|
|
||||||
|
Versions of Major Components
|
||||||
|
---------------------
|
||||||
|
Apache Tika 1.3
|
||||||
|
Carrot2 3.6.2
|
||||||
|
Velocity 1.7 and Velocity Tools 2.0
|
||||||
|
Apache UIMA 2.3.1
|
||||||
|
Apache ZooKeeper 3.4.5
|
||||||
|
|
||||||
|
Upgrading from Solr 4.2.0
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
(No upgrade instructions yet)
|
||||||
|
|
||||||
|
Detailed Change List
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
New Features
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Bug Fixes
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Other Changes
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
* SOLR-4537: Clean up schema information REST API. (Steve Rowe)
|
||||||
|
|
||||||
================== 4.2.0 ==================
|
================== 4.2.0 ==================
|
||||||
|
|
||||||
Versions of Major Components
|
Versions of Major Components
|
||||||
|
|
|
@ -18,14 +18,10 @@ package org.apache.solr.rest;
|
||||||
|
|
||||||
import org.apache.solr.common.params.CommonParams;
|
import org.apache.solr.common.params.CommonParams;
|
||||||
import org.apache.solr.common.util.SimpleOrderedMap;
|
import org.apache.solr.common.util.SimpleOrderedMap;
|
||||||
import org.apache.solr.schema.CopyField;
|
|
||||||
import org.apache.solr.schema.IndexSchema;
|
|
||||||
import org.apache.solr.schema.SchemaField;
|
import org.apache.solr.schema.SchemaField;
|
||||||
import org.restlet.resource.ResourceException;
|
import org.restlet.resource.ResourceException;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,10 +34,10 @@ abstract class BaseFieldResource extends BaseSchemaResource {
|
||||||
private static final String SHOW_DEFAULTS = "showDefaults";
|
private static final String SHOW_DEFAULTS = "showDefaults";
|
||||||
|
|
||||||
|
|
||||||
private LinkedHashMap<String,SimpleOrderedMap<Object>> requestedFields;
|
private LinkedHashSet<String> requestedFields;
|
||||||
private boolean showDefaults;
|
private boolean showDefaults;
|
||||||
|
|
||||||
protected LinkedHashMap<String,SimpleOrderedMap<Object>> getRequestedFields() {
|
protected LinkedHashSet<String> getRequestedFields() {
|
||||||
return requestedFields;
|
return requestedFields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,10 +66,10 @@ abstract class BaseFieldResource extends BaseSchemaResource {
|
||||||
if (null != flParam) {
|
if (null != flParam) {
|
||||||
String[] fields = flParam.trim().split("[,\\s]+");
|
String[] fields = flParam.trim().split("[,\\s]+");
|
||||||
if (fields.length > 0) {
|
if (fields.length > 0) {
|
||||||
requestedFields = new LinkedHashMap<String,SimpleOrderedMap<Object>>();
|
requestedFields = new LinkedHashSet<String>();
|
||||||
for (String field : fields) {
|
for (String field : fields) {
|
||||||
if ( ! field.isEmpty()) {
|
if ( ! field.trim().isEmpty()) {
|
||||||
requestedFields.put(field, null);
|
requestedFields.add(field.trim());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,9 +89,9 @@ abstract class BaseFieldResource extends BaseSchemaResource {
|
||||||
SimpleOrderedMap<Object> properties = field.getNamedPropertyValues(showDefaults);
|
SimpleOrderedMap<Object> properties = field.getNamedPropertyValues(showDefaults);
|
||||||
if ( ! getSchema().getFields().containsKey(field.getName())) {
|
if ( ! getSchema().getFields().containsKey(field.getName())) {
|
||||||
String dynamicBase = getSchema().getDynamicPattern(field.getName());
|
String dynamicBase = getSchema().getDynamicPattern(field.getName());
|
||||||
|
// Add dynamicBase property if it's different from the field name.
|
||||||
if ( ! field.getName().equals(dynamicBase)) {
|
if ( ! field.getName().equals(dynamicBase)) {
|
||||||
// Don't add dynamicBase property if it's identical to the field name.
|
properties.add(DYNAMIC_BASE, dynamicBase);
|
||||||
properties.add(DYNAMIC_BASE, getSchema().getDynamicPattern(field.getName()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (field == getSchema().getUniqueKeyField()) {
|
if (field == getSchema().getUniqueKeyField()) {
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.apache.solr.common.SolrException.ErrorCode;
|
||||||
import org.apache.solr.common.params.CommonParams;
|
import org.apache.solr.common.params.CommonParams;
|
||||||
import org.apache.solr.common.util.SimpleOrderedMap;
|
import org.apache.solr.common.util.SimpleOrderedMap;
|
||||||
import org.apache.solr.schema.FieldType;
|
import org.apache.solr.schema.FieldType;
|
||||||
|
import org.apache.solr.schema.IndexSchema;
|
||||||
import org.apache.solr.schema.SchemaField;
|
import org.apache.solr.schema.SchemaField;
|
||||||
import org.restlet.representation.Representation;
|
import org.restlet.representation.Representation;
|
||||||
import org.restlet.resource.ResourceException;
|
import org.restlet.resource.ResourceException;
|
||||||
|
@ -28,6 +29,7 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -55,32 +57,29 @@ public class DynamicFieldCollectionResource extends BaseFieldResource implements
|
||||||
public Representation get() {
|
public Representation get() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SchemaField[] dynamicFields = getSchema().getDynamicFieldPrototypes();
|
List<SimpleOrderedMap<Object>> props = new ArrayList<SimpleOrderedMap<Object>>();
|
||||||
List<SimpleOrderedMap<Object>> props = new ArrayList<SimpleOrderedMap<Object>>(dynamicFields.length);
|
if (null == getRequestedFields()) {
|
||||||
if (null != getRequestedFields()) {
|
for (IndexSchema.DynamicField dynamicField : getSchema().getDynamicFields()) {
|
||||||
|
if ( ! dynamicField.getRegex().startsWith(INTERNAL_POLY_FIELD_PREFIX)) { // omit internal polyfields
|
||||||
|
props.add(getFieldProperties(dynamicField.getPrototype()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (0 == getRequestedFields().size()) {
|
if (0 == getRequestedFields().size()) {
|
||||||
String message = "Empty " + CommonParams.FL + " parameter value";
|
String message = "Empty " + CommonParams.FL + " parameter value";
|
||||||
throw new SolrException(ErrorCode.BAD_REQUEST, message);
|
throw new SolrException(ErrorCode.BAD_REQUEST, message);
|
||||||
}
|
}
|
||||||
for (SchemaField prototype : dynamicFields) {
|
Map<String,SchemaField> dynamicFieldsByName = new HashMap<String,SchemaField>();
|
||||||
if (getRequestedFields().containsKey(prototype.getName())) {
|
for (IndexSchema.DynamicField dynamicField : getSchema().getDynamicFields()) {
|
||||||
getRequestedFields().put(prototype.getName(), getFieldProperties(prototype));
|
dynamicFieldsByName.put(dynamicField.getRegex(), dynamicField.getPrototype());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Use the same order as the fl parameter
|
// Use the same order as the fl parameter
|
||||||
for (Map.Entry<String,SimpleOrderedMap<Object>> requestedField : getRequestedFields().entrySet()) {
|
for (String dynamicFieldName : getRequestedFields()) {
|
||||||
SimpleOrderedMap<Object> fieldProperties = requestedField.getValue();
|
final SchemaField dynamicSchemaField = dynamicFieldsByName.get(dynamicFieldName);
|
||||||
// Should there be some form of error condition
|
if (null == dynamicSchemaField) {
|
||||||
// if one or more of the requested fields were not found?
|
log.info("Requested dynamic field '" + dynamicFieldName + "' not found.");
|
||||||
if (null != fieldProperties) {
|
|
||||||
props.add(fieldProperties);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
for (SchemaField prototype : dynamicFields) {
|
props.add(getFieldProperties(dynamicSchemaField));
|
||||||
// omit internal polyfields
|
|
||||||
if ( ! prototype.getName().startsWith(INTERNAL_POLY_FIELD_PREFIX)) {
|
|
||||||
props.add(getFieldProperties(prototype));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,29 +21,37 @@ import org.apache.solr.common.SolrException;
|
||||||
import org.apache.solr.common.SolrException.ErrorCode;
|
import org.apache.solr.common.SolrException.ErrorCode;
|
||||||
import org.apache.solr.common.params.CommonParams;
|
import org.apache.solr.common.params.CommonParams;
|
||||||
import org.apache.solr.common.util.SimpleOrderedMap;
|
import org.apache.solr.common.util.SimpleOrderedMap;
|
||||||
|
import org.apache.solr.schema.SchemaField;
|
||||||
import org.restlet.representation.Representation;
|
import org.restlet.representation.Representation;
|
||||||
import org.restlet.resource.ResourceException;
|
import org.restlet.resource.ResourceException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.SortedSet;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class responds to requests at /solr/(corename)/schema/fields
|
* This class responds to requests at /solr/(corename)/schema/fields
|
||||||
* <p/>
|
* <p/>
|
||||||
* One query parameters are supported:
|
* Two query parameters are supported:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>
|
* <li>
|
||||||
* "fl": a comma- and/or space-separated list of fields to send properties
|
* "fl": a comma- and/or space-separated list of fields to send properties
|
||||||
* for in the response, rather than the default: all of them.
|
* for in the response, rather than the default: all of them.
|
||||||
* </li>
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* "includeDynamic": if the "fl" parameter is specified, matching dynamic
|
||||||
|
* fields are included in the response and identified with the "dynamicBase"
|
||||||
|
* property. If the "fl" parameter is not specified, the "includeDynamic"
|
||||||
|
* query parameter is ignored.
|
||||||
|
* </li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public class FieldCollectionResource extends BaseFieldResource implements GETable {
|
public class FieldCollectionResource extends BaseFieldResource implements GETable {
|
||||||
private static final Logger log = LoggerFactory.getLogger(FieldCollectionResource.class);
|
private static final Logger log = LoggerFactory.getLogger(FieldCollectionResource.class);
|
||||||
|
private boolean includeDynamic;
|
||||||
|
|
||||||
public FieldCollectionResource() {
|
public FieldCollectionResource() {
|
||||||
super();
|
super();
|
||||||
|
@ -52,40 +60,39 @@ public class FieldCollectionResource extends BaseFieldResource implements GETabl
|
||||||
@Override
|
@Override
|
||||||
public void doInit() throws ResourceException {
|
public void doInit() throws ResourceException {
|
||||||
super.doInit();
|
super.doInit();
|
||||||
|
includeDynamic = getSolrRequest().getParams().getBool(INCLUDE_DYNAMIC_PARAM, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Representation get() {
|
public Representation get() {
|
||||||
try {
|
try {
|
||||||
// Get all explicitly defined fields from the schema
|
final List<SimpleOrderedMap<Object>> props = new ArrayList<SimpleOrderedMap<Object>>();
|
||||||
Set<String> fieldNames = new HashSet<String>(getSchema().getFields().keySet());
|
|
||||||
|
|
||||||
final List<SimpleOrderedMap<Object>> fieldCollectionProperties = new ArrayList<SimpleOrderedMap<Object>>(fieldNames.size());
|
|
||||||
|
|
||||||
if (null == getRequestedFields()) {
|
if (null == getRequestedFields()) {
|
||||||
|
SortedSet<String> fieldNames = new TreeSet<String>(getSchema().getFields().keySet());
|
||||||
for (String fieldName : fieldNames) {
|
for (String fieldName : fieldNames) {
|
||||||
fieldCollectionProperties.add(getFieldProperties(getSchema().getFieldOrNull(fieldName)));
|
props.add(getFieldProperties(getSchema().getFields().get(fieldName)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (0 == getRequestedFields().size()) {
|
if (0 == getRequestedFields().size()) {
|
||||||
String message = "Empty " + CommonParams.FL + " parameter value";
|
String message = "Empty " + CommonParams.FL + " parameter value";
|
||||||
throw new SolrException(ErrorCode.BAD_REQUEST, message);
|
throw new SolrException(ErrorCode.BAD_REQUEST, message);
|
||||||
}
|
}
|
||||||
for (String field : fieldNames) {
|
|
||||||
if (getRequestedFields().containsKey(field)) {
|
|
||||||
getRequestedFields().put(field, getFieldProperties(getSchema().getFieldOrNull(field)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Use the same order as the fl parameter
|
// Use the same order as the fl parameter
|
||||||
for (SimpleOrderedMap<Object> fieldProperties : getRequestedFields().values()) {
|
for (String fieldName : getRequestedFields()) {
|
||||||
// Should there be some form of error condition
|
final SchemaField field;
|
||||||
// if one or more of the requested fields were not found?
|
if (includeDynamic) {
|
||||||
if (null != fieldProperties) {
|
field = getSchema().getFieldOrNull(fieldName);
|
||||||
fieldCollectionProperties.add(fieldProperties);
|
} else {
|
||||||
|
field = getSchema().getFields().get(fieldName);
|
||||||
|
}
|
||||||
|
if (null == field) {
|
||||||
|
log.info("Requested field '" + fieldName + "' not found.");
|
||||||
|
} else {
|
||||||
|
props.add(getFieldProperties(field));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getSolrResponse().add(SchemaRestApi.FIELDS, fieldCollectionProperties);
|
getSolrResponse().add(SchemaRestApi.FIELDS, props);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
getSolrResponse().setException(e);
|
getSolrResponse().setException(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,11 +68,10 @@ public class FieldResource extends BaseFieldResource implements GETable {
|
||||||
final String message = "Field name is missing";
|
final String message = "Field name is missing";
|
||||||
throw new SolrException(ErrorCode.BAD_REQUEST, message);
|
throw new SolrException(ErrorCode.BAD_REQUEST, message);
|
||||||
} else {
|
} else {
|
||||||
SchemaField field;
|
final SchemaField field;
|
||||||
if (includeDynamic) {
|
if (includeDynamic) {
|
||||||
field = getSchema().getFieldOrNull(fieldName);
|
field = getSchema().getFieldOrNull(fieldName);
|
||||||
} else {
|
} else {
|
||||||
// Don't look for matches among dynamic fields
|
|
||||||
field = getSchema().getFields().get(fieldName);
|
field = getSchema().getFields().get(fieldName);
|
||||||
}
|
}
|
||||||
if (null == field) {
|
if (null == field) {
|
||||||
|
|
|
@ -841,7 +841,8 @@ public final class IndexSchema {
|
||||||
|
|
||||||
|
|
||||||
public final static class DynamicField extends DynamicReplacement {
|
public final static class DynamicField extends DynamicReplacement {
|
||||||
final SchemaField prototype;
|
private final SchemaField prototype;
|
||||||
|
public SchemaField getPrototype() { return prototype; }
|
||||||
|
|
||||||
DynamicField(SchemaField prototype) {
|
DynamicField(SchemaField prototype) {
|
||||||
super(prototype.name);
|
super(prototype.name);
|
||||||
|
|
|
@ -24,9 +24,9 @@ public class TestFieldCollectionResource extends SchemaRestletTestBase {
|
||||||
@Test
|
@Test
|
||||||
public void testGetAllFields() throws Exception {
|
public void testGetAllFields() throws Exception {
|
||||||
assertQ("/schema/fields?indent=on&wt=xml",
|
assertQ("/schema/fields?indent=on&wt=xml",
|
||||||
"(/response/arr[@name='fields']/lst/str[@name='name'])[1] = 'custstopfilt'",
|
"(/response/arr[@name='fields']/lst/str[@name='name'])[1] = 'HTMLstandardtok'",
|
||||||
"(/response/arr[@name='fields']/lst/str[@name='name'])[2] = 'lowerfilt'",
|
"(/response/arr[@name='fields']/lst/str[@name='name'])[2] = 'HTMLwhitetok'",
|
||||||
"(/response/arr[@name='fields']/lst/str[@name='name'])[3] = 'test_basictv'",
|
"(/response/arr[@name='fields']/lst/str[@name='name'])[3] = '_version_'",
|
||||||
"count(//copySources/str) = count(//copyDests/str)");
|
"count(//copySources/str) = count(//copyDests/str)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,31 @@ public class TestFieldCollectionResource extends SchemaRestletTestBase {
|
||||||
"(/response/arr[@name='fields']/lst/str[@name='name'])[2] = '_version_'");
|
"(/response/arr[@name='fields']/lst/str[@name='name'])[2] = '_version_'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetThreeFieldsDontIncludeDynamic() throws IOException {
|
||||||
|
//
|
||||||
|
assertQ("/schema/fields?indent=on&wt=xml&fl=id,_version_,price_i",
|
||||||
|
"count(/response/arr[@name='fields']/lst/str[@name='name']) = 2",
|
||||||
|
"(/response/arr[@name='fields']/lst/str[@name='name'])[1] = 'id'",
|
||||||
|
"(/response/arr[@name='fields']/lst/str[@name='name'])[2] = '_version_'");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetThreeFieldsIncludeDynamic() throws IOException {
|
||||||
|
assertQ("/schema/fields?indent=on&wt=xml&fl=id,_version_,price_i&includeDynamic=on",
|
||||||
|
|
||||||
|
"count(/response/arr[@name='fields']/lst/str[@name='name']) = 3",
|
||||||
|
|
||||||
|
"(/response/arr[@name='fields']/lst/str[@name='name'])[1] = 'id'",
|
||||||
|
|
||||||
|
"(/response/arr[@name='fields']/lst/str[@name='name'])[2] = '_version_'",
|
||||||
|
|
||||||
|
"(/response/arr[@name='fields']/lst/str[@name='name'])[3] = 'price_i'",
|
||||||
|
|
||||||
|
"/response/arr[@name='fields']/lst[ str[@name='name']='price_i' "
|
||||||
|
+" and str[@name='dynamicBase']='*_i']");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNotFoundFields() throws IOException {
|
public void testNotFoundFields() throws IOException {
|
||||||
assertQ("/schema/fields?indent=on&wt=xml&fl=not_in_there,this_one_either",
|
assertQ("/schema/fields?indent=on&wt=xml&fl=not_in_there,this_one_either",
|
||||||
|
@ -48,9 +73,9 @@ public class TestFieldCollectionResource extends SchemaRestletTestBase {
|
||||||
@Test
|
@Test
|
||||||
public void testJsonGetAllFields() throws Exception {
|
public void testJsonGetAllFields() throws Exception {
|
||||||
assertJQ("/schema/fields?indent=on",
|
assertJQ("/schema/fields?indent=on",
|
||||||
"/fields/[0]/name=='custstopfilt'",
|
"/fields/[0]/name=='HTMLstandardtok'",
|
||||||
"/fields/[1]/name=='lowerfilt'",
|
"/fields/[1]/name=='HTMLwhitetok'",
|
||||||
"/fields/[2]/name=='test_basictv'");
|
"/fields/[2]/name=='_version_'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue