diff --git a/dev-tools/maven/lucene/sandbox/pom.xml.template b/dev-tools/maven/lucene/sandbox/pom.xml.template
index d357c6465e4..baa8a3c04db 100644
--- a/dev-tools/maven/lucene/sandbox/pom.xml.template
+++ b/dev-tools/maven/lucene/sandbox/pom.xml.template
@@ -48,13 +48,6 @@
lucene-test-framework
test
-
- org.apache.lucene
- lucene-spatial
- ${project.version}
- test-jar
- test
-
@lucene-sandbox.internal.dependencies@
@lucene-sandbox.external.dependencies@
@lucene-sandbox.internal.test.dependencies@
diff --git a/lucene/sandbox/build.xml b/lucene/sandbox/build.xml
index 4323241e2ed..93bc2754ece 100644
--- a/lucene/sandbox/build.xml
+++ b/lucene/sandbox/build.xml
@@ -23,39 +23,4 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lucene/sandbox/src/test/org/apache/lucene/search/TestLatLonPointQueries.java b/lucene/sandbox/src/test/org/apache/lucene/search/TestLatLonPointQueries.java
index 8c909e6b593..39c7a045832 100644
--- a/lucene/sandbox/src/test/org/apache/lucene/search/TestLatLonPointQueries.java
+++ b/lucene/sandbox/src/test/org/apache/lucene/search/TestLatLonPointQueries.java
@@ -18,7 +18,7 @@ package org.apache.lucene.search;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.LatLonPoint;
-import org.apache.lucene.spatial.util.BaseGeoPointTestCase;
+import org.apache.lucene.geo.BaseGeoPointTestCase;
import org.apache.lucene.geo.Polygon;
import org.apache.lucene.geo.GeoEncodingUtils;
diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestGeoPointQuery.java b/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestGeoPointQuery.java
index 7e64430be41..e5b766daa64 100644
--- a/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestGeoPointQuery.java
+++ b/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestGeoPointQuery.java
@@ -19,11 +19,11 @@ package org.apache.lucene.spatial.geopoint.search;
import org.apache.lucene.document.Document;
import org.apache.lucene.search.Query;
import org.apache.lucene.spatial.util.GeoEncodingUtils;
+import org.apache.lucene.geo.BaseGeoPointTestCase;
import org.apache.lucene.geo.Polygon;
import org.apache.lucene.geo.Rectangle;
import org.apache.lucene.spatial.geopoint.document.GeoPointField;
import org.apache.lucene.spatial.geopoint.document.GeoPointField.TermEncoding;
-import org.apache.lucene.spatial.util.BaseGeoPointTestCase;
/**
* random testing for GeoPoint query logic
diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestLegacyGeoPointQuery.java b/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestLegacyGeoPointQuery.java
index 75cc377d0e5..d0b57fe9d4f 100644
--- a/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestLegacyGeoPointQuery.java
+++ b/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestLegacyGeoPointQuery.java
@@ -19,11 +19,11 @@ package org.apache.lucene.spatial.geopoint.search;
import org.apache.lucene.document.Document;
import org.apache.lucene.search.Query;
import org.apache.lucene.spatial.util.GeoEncodingUtils;
+import org.apache.lucene.geo.BaseGeoPointTestCase;
import org.apache.lucene.geo.Polygon;
import org.apache.lucene.geo.Rectangle;
import org.apache.lucene.spatial.geopoint.document.GeoPointField;
import org.apache.lucene.spatial.geopoint.document.GeoPointField.TermEncoding;
-import org.apache.lucene.spatial.util.BaseGeoPointTestCase;
/**
* random testing for GeoPoint query logic (with deprecated numeric encoding)
diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/util/BaseGeoPointTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/geo/BaseGeoPointTestCase.java
similarity index 99%
rename from lucene/spatial/src/test/org/apache/lucene/spatial/util/BaseGeoPointTestCase.java
rename to lucene/test-framework/src/java/org/apache/lucene/geo/BaseGeoPointTestCase.java
index daf3cbda197..dbdf189f3c4 100644
--- a/lucene/spatial/src/test/org/apache/lucene/spatial/util/BaseGeoPointTestCase.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/geo/BaseGeoPointTestCase.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.lucene.spatial.util;
+package org.apache.lucene.geo;
import java.io.IOException;
import java.text.DecimalFormat;
@@ -771,13 +771,16 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
static final boolean rectContainsPoint(Rectangle rect, double pointLat, double pointLon) {
assert Double.isNaN(pointLat) == false;
+
+ if (pointLat < rect.minLat || pointLat > rect.maxLat) {
+ return false;
+ }
if (rect.minLon <= rect.maxLon) {
- return GeoRelationUtils.pointInRectPrecise(pointLat, pointLon, rect.minLat, rect.maxLat, rect.minLon, rect.maxLon);
+ return pointLon >= rect.minLon && pointLon <= rect.maxLon;
} else {
// Rect crosses dateline:
- return GeoRelationUtils.pointInRectPrecise(pointLat, pointLon, rect.minLat, rect.maxLat, -180.0, rect.maxLon)
- || GeoRelationUtils.pointInRectPrecise(pointLat, pointLon, rect.minLat, rect.maxLat, rect.minLon, 180.0);
+ return pointLon <= rect.maxLon || pointLon >= rect.minLon;
}
}
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 2b6c868bb5c..5d81091f59a 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -120,7 +120,12 @@ Bug Fixes
(Nicolas Gavalda, Jorge Luis Betancourt Gonzalez via Mark Miller)
* SOLR-8946: bin/post failed to detect stdin usage on Ubuntu; maybe other unixes. (David Smiley)
-
+
+* SOLR-8662: SchemaManager waits correctly for replicas to be notified of a new change.
+ (sarowe, Noble Paul, Varun Thacker)
+
+* SOLR-9004: Fix "name" field type definition in films example. (Alexandre Rafalovitch via Varun Thacker)
+
Optimizations
----------------------
* SOLR-8722: Don't force a full ZkStateReader refresh on every Overseer operation.
diff --git a/solr/core/src/java/org/apache/solr/cloud/ZkSolrResourceLoader.java b/solr/core/src/java/org/apache/solr/cloud/ZkSolrResourceLoader.java
index 4d12db906d4..2b60e53ea70 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ZkSolrResourceLoader.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ZkSolrResourceLoader.java
@@ -80,17 +80,42 @@ public class ZkSolrResourceLoader extends SolrResourceLoader {
*/
@Override
public InputStream openResource(String resource) throws IOException {
- InputStream is = null;
+ InputStream is;
String file = configSetZkPath + "/" + resource;
- try {
- if (zkController.pathExists(file)) {
- Stat stat = new Stat();
- byte[] bytes = zkController.getZkClient().getData(file, null, stat, true);
- return new ZkByteArrayInputStream(bytes, stat);
+ int maxTries = 10;
+ Exception exception = null;
+ while (maxTries -- > 0) {
+ try {
+ if (zkController.pathExists(file)) {
+ Stat stat = new Stat();
+ byte[] bytes = zkController.getZkClient().getData(file, null, stat, true);
+ return new ZkByteArrayInputStream(bytes, stat);
+ } else {
+ //Path does not exists. We only retry for session expired exceptions.
+ break;
+ }
+ } catch (KeeperException.SessionExpiredException e) {
+ exception = e;
+ // Retry in case of session expiry
+ try {
+ Thread.sleep(1000);
+ log.debug("Sleeping for 1s before retrying fetching resource=" + resource);
+ } catch (InterruptedException ie) {
+ Thread.currentThread().interrupt();
+ throw new IOException("Could not load resource=" + resource, ie);
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new IOException("Error opening " + file, e);
+ } catch (KeeperException e) {
+ throw new IOException("Error opening " + file, e);
}
- } catch (Exception e) {
- throw new IOException("Error opening " + file, e);
}
+
+ if (exception != null) {
+ throw new IOException("We re-tried 10 times but was still unable to fetch resource=" + resource + " from ZK", exception);
+ }
+
try {
// delegate to the class loader (looking into $INSTANCE_DIR/lib jars)
is = classLoader.getResourceAsStream(resource.replace(File.separatorChar, '/'));
diff --git a/solr/core/src/java/org/apache/solr/schema/SchemaManager.java b/solr/core/src/java/org/apache/solr/schema/SchemaManager.java
index e70b84ffc0f..3b492a75dbe 100644
--- a/solr/core/src/java/org/apache/solr/schema/SchemaManager.java
+++ b/solr/core/src/java/org/apache/solr/schema/SchemaManager.java
@@ -25,6 +25,7 @@ import org.apache.solr.core.SolrResourceLoader;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.rest.BaseSolrResource;
import org.apache.solr.util.CommandOperation;
+import org.apache.solr.util.TimeOut;
import org.apache.zookeeper.KeeperException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -86,20 +87,27 @@ public class SchemaManager {
if (!errs.isEmpty()) return errs;
IndexSchema schema = req.getCore().getLatestSchema();
- if (!(schema instanceof ManagedIndexSchema)) {
+ if (schema instanceof ManagedIndexSchema && schema.isMutable()) {
+ synchronized (schema.getSchemaUpdateLock()) {
+ return doOperations(ops);
+ }
+ } else {
return singletonList(singletonMap(CommandOperation.ERR_MSGS, "schema is not editable"));
}
- synchronized (schema.getSchemaUpdateLock()) {
- return doOperations(ops);
- }
}
private List doOperations(List operations) throws InterruptedException, IOException, KeeperException {
- int timeout = req.getParams().getInt(BaseSolrResource.UPDATE_TIMEOUT_SECS, -1);
- long startTime = System.nanoTime();
- long endTime = timeout > 0 ? System.nanoTime() + (timeout * 1000 * 1000) : Long.MAX_VALUE;
+ //The default timeout is 10 minutes when no BaseSolrResource.UPDATE_TIMEOUT_SECS is specified
+ int timeout = req.getParams().getInt(BaseSolrResource.UPDATE_TIMEOUT_SECS, 600);
+
+ //If BaseSolrResource.UPDATE_TIMEOUT_SECS=0 or -1 then end time then we'll try for 10 mins ( default timeout )
+ if (timeout < 1) {
+ timeout = 600;
+ }
+ TimeOut timeOut = new TimeOut(timeout, TimeUnit.SECONDS);
SolrCore core = req.getCore();
- while (System.nanoTime() < endTime) {
+ String errorMsg = "Unable to persist managed schema. ";
+ while (!timeOut.hasTimedOut()) {
managedIndexSchema = getFreshManagedSchema();
for (CommandOperation op : operations) {
OpType opType = OpType.get(op.name);
@@ -118,25 +126,18 @@ public class SchemaManager {
try {
managedIndexSchema.persist(sw);
} catch (IOException e) {
- log.info("race condition ");
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "unable to serialize schema");
//unlikely
}
try {
- ZkController.persistConfigResourceToZooKeeper(zkLoader,
- managedIndexSchema.getSchemaZkVersion(),
- managedIndexSchema.getResourceName(),
- sw.toString().getBytes(StandardCharsets.UTF_8),
- true);
- waitForOtherReplicasToUpdate(timeout, startTime);
+ ZkController.persistConfigResourceToZooKeeper(zkLoader, managedIndexSchema.getSchemaZkVersion(),
+ managedIndexSchema.getResourceName(), sw.toString().getBytes(StandardCharsets.UTF_8), true);
+ waitForOtherReplicasToUpdate(timeOut);
+ core.setLatestSchema(managedIndexSchema);
return Collections.emptyList();
} catch (ZkController.ResourceModifiedInZkException e) {
- log.info("Race condition schema modified by another node");
- } catch (Exception e) {
- String s = "Exception persisting schema";
- log.warn(s, e);
- return singletonList(s + e.getMessage());
+ log.info("Schema was modified by another node. Retrying..");
}
} else {
try {
@@ -144,36 +145,30 @@ public class SchemaManager {
managedIndexSchema.persistManagedSchema(false);
core.setLatestSchema(managedIndexSchema);
return Collections.emptyList();
- } catch (ManagedIndexSchema.SchemaChangedInZkException e) {
- String s = "Failed to update schema because schema is modified";
- log.warn(s, e);
- } catch (Exception e) {
- String s = "Exception persisting schema";
- log.warn(s, e);
- return singletonList(s + e.getMessage());
+ } catch (SolrException e) {
+ log.warn(errorMsg);
+ return singletonList(errorMsg + e.getMessage());
}
}
}
- return singletonList("Unable to persist schema");
+ log.warn(errorMsg + "Timed out.");
+ return singletonList(errorMsg + "Timed out.");
}
- private void waitForOtherReplicasToUpdate(int timeout, long startTime) {
- if (timeout > 0 && managedIndexSchema.getResourceLoader() instanceof ZkSolrResourceLoader) {
- CoreDescriptor cd = req.getCore().getCoreDescriptor();
- String collection = cd.getCollectionName();
- if (collection != null) {
- ZkSolrResourceLoader zkLoader = (ZkSolrResourceLoader) managedIndexSchema.getResourceLoader();
- long timeLeftSecs = timeout - TimeUnit.SECONDS.convert(System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
- if (timeLeftSecs <= 0) {
- throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
- "Not enough time left to update replicas. However, the schema is updated already.");
- }
- ManagedIndexSchema.waitForSchemaZkVersionAgreement(collection,
- cd.getCloudDescriptor().getCoreNodeName(),
- (managedIndexSchema).getSchemaZkVersion(),
- zkLoader.getZkController(),
- (int) timeLeftSecs);
+ private void waitForOtherReplicasToUpdate(TimeOut timeOut) {
+ CoreDescriptor cd = req.getCore().getCoreDescriptor();
+ String collection = cd.getCollectionName();
+ if (collection != null) {
+ ZkSolrResourceLoader zkLoader = (ZkSolrResourceLoader) managedIndexSchema.getResourceLoader();
+ if (timeOut.hasTimedOut()) {
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
+ "Not enough time left to update replicas. However, the schema is updated already.");
}
+ ManagedIndexSchema.waitForSchemaZkVersionAgreement(collection,
+ cd.getCloudDescriptor().getCoreNodeName(),
+ (managedIndexSchema).getSchemaZkVersion(),
+ zkLoader.getZkController(),
+ (int) timeOut.timeLeft(TimeUnit.SECONDS));
}
}
@@ -198,7 +193,7 @@ public class SchemaManager {
@Override public boolean perform(CommandOperation op, SchemaManager mgr) {
String src = op.getStr(SOURCE);
List dests = op.getStrs(DESTINATION);
-
+
int maxChars = CopyField.UNLIMITED; // If maxChars is not specified, there is no limit on copied chars
String maxCharsStr = op.getStr(MAX_CHARS, null);
if (null != maxCharsStr) {
@@ -241,7 +236,7 @@ public class SchemaManager {
}
try {
SchemaField field = SchemaField.create(name, ft, op.getValuesExcluding(NAME, TYPE));
- mgr.managedIndexSchema
+ mgr.managedIndexSchema
= mgr.managedIndexSchema.addFields(singletonList(field), Collections.emptyMap(), false);
return true;
} catch (Exception e) {
@@ -262,8 +257,8 @@ public class SchemaManager {
return false;
}
try {
- SchemaField field = SchemaField.create(name, ft, op.getValuesExcluding(NAME, TYPE));
- mgr.managedIndexSchema
+ SchemaField field = SchemaField.create(name, ft, op.getValuesExcluding(NAME, TYPE));
+ mgr.managedIndexSchema
= mgr.managedIndexSchema.addDynamicFields(singletonList(field), Collections.emptyMap(), false);
return true;
} catch (Exception e) {
@@ -297,7 +292,7 @@ public class SchemaManager {
if (op.hasError())
return false;
if ( ! op.getValuesExcluding(SOURCE, DESTINATION).isEmpty()) {
- op.addError("Only the '" + SOURCE + "' and '" + DESTINATION
+ op.addError("Only the '" + SOURCE + "' and '" + DESTINATION
+ "' params are allowed with the 'delete-copy-field' operation");
return false;
}
@@ -318,14 +313,14 @@ public class SchemaManager {
if ( ! op.getValuesExcluding(NAME).isEmpty()) {
op.addError("Only the '" + NAME + "' param is allowed with the 'delete-field' operation");
return false;
- }
+ }
try {
mgr.managedIndexSchema = mgr.managedIndexSchema.deleteFields(singleton(name));
return true;
} catch (Exception e) {
op.addError(getErrorStr(e));
return false;
- }
+ }
}
},
DELETE_DYNAMIC_FIELD("delete-dynamic-field") {
@@ -436,7 +431,7 @@ public class SchemaManager {
int version = ((ZkSolrResourceLoader.ZkByteArrayInputStream) in).getStat().getVersion();
log.info("managed schema loaded . version : {} ", version);
return new ManagedIndexSchema
- (req.getCore().getSolrConfig(), req.getSchema().getResourceName(), new InputSource(in),
+ (req.getCore().getSolrConfig(), req.getSchema().getResourceName(), new InputSource(in),
true, req.getSchema().getResourceName(), version, req.getSchema().getSchemaUpdateLock());
} else {
return (ManagedIndexSchema) req.getCore().getLatestSchema();
diff --git a/solr/core/src/test-files/solr/configsets/configset-1/conf/schema-minimal.xml b/solr/core/src/test-files/solr/configsets/cloud-managed/conf/managed-schema
similarity index 65%
rename from solr/core/src/test-files/solr/configsets/configset-1/conf/schema-minimal.xml
rename to solr/core/src/test-files/solr/configsets/cloud-managed/conf/managed-schema
index 9e2f9471026..fd7be8308f9 100644
--- a/solr/core/src/test-files/solr/configsets/configset-1/conf/schema-minimal.xml
+++ b/solr/core/src/test-files/solr/configsets/cloud-managed/conf/managed-schema
@@ -18,8 +18,14 @@
+
+
-
+
+
+
+
+ id
diff --git a/solr/core/src/test-files/solr/configsets/configset-1/conf/solrconfig-minimal.xml b/solr/core/src/test-files/solr/configsets/cloud-managed/conf/solrconfig.xml
similarity index 72%
rename from solr/core/src/test-files/solr/configsets/configset-1/conf/solrconfig-minimal.xml
rename to solr/core/src/test-files/solr/configsets/cloud-managed/conf/solrconfig.xml
index a6fe5bae8fa..aabfa2f9b66 100644
--- a/solr/core/src/test-files/solr/configsets/configset-1/conf/solrconfig-minimal.xml
+++ b/solr/core/src/test-files/solr/configsets/cloud-managed/conf/solrconfig.xml
@@ -17,16 +17,7 @@
limitations under the License.
-->
-
+
@@ -34,7 +25,11 @@
-
+
+
+ ${managed.schema.mutable}
+ managed-schema
+
${tests.luceneMatchVersion:LATEST}
@@ -42,8 +37,9 @@
${solr.commitwithin.softcommit:true}
-
+
+
explicit
@@ -53,4 +49,3 @@
-
diff --git a/solr/core/src/test/org/apache/solr/schema/TestManagedSchemaAPI.java b/solr/core/src/test/org/apache/solr/schema/TestManagedSchemaAPI.java
new file mode 100644
index 00000000000..3bd4dea938b
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/schema/TestManagedSchemaAPI.java
@@ -0,0 +1,101 @@
+package org.apache.solr.schema;
+
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.request.UpdateRequest;
+import org.apache.solr.client.solrj.request.schema.SchemaRequest;
+import org.apache.solr.client.solrj.response.CollectionAdminResponse;
+import org.apache.solr.client.solrj.response.schema.SchemaResponse;
+import org.apache.solr.cloud.SolrCloudTestCase;
+import org.apache.solr.common.SolrInputDocument;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class TestManagedSchemaAPI extends SolrCloudTestCase {
+ private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ @BeforeClass
+ public static void createCluster() throws Exception {
+ System.setProperty("managed.schema.mutable", "true");
+ configureCluster(2)
+ .addConfig("conf1", TEST_PATH().resolve("configsets").resolve("cloud-managed").resolve("conf"))
+ .configure();
+ }
+
+ @Test
+ public void test() throws Exception {
+ String collection = "testschemaapi";
+ cluster.createCollection(collection, 1, 2, "conf1", null);
+ testReloadAndAddSimple(collection);
+ testAddFieldAndDocument(collection);
+ }
+
+ private void testReloadAndAddSimple(String collection) throws IOException, SolrServerException {
+ CloudSolrClient cloudClient = cluster.getSolrClient();
+
+ String fieldName = "myNewField";
+ addStringField(fieldName, collection, cloudClient);
+
+ CollectionAdminRequest.Reload reloadRequest = CollectionAdminRequest.reloadCollection(collection);
+ CollectionAdminResponse response = reloadRequest.process(cloudClient);
+ assertEquals(0, response.getStatus());
+ assertTrue(response.isSuccess());
+
+ SolrInputDocument doc = new SolrInputDocument();
+ doc.addField("id", "1");
+ doc.addField(fieldName, "val");
+ UpdateRequest ureq = new UpdateRequest().add(doc);
+ cloudClient.request(ureq, collection);
+ }
+
+ private void testAddFieldAndDocument(String collection) throws IOException, SolrServerException {
+ CloudSolrClient cloudClient = cluster.getSolrClient();
+
+ String fieldName = "myNewField1";
+ addStringField(fieldName, collection, cloudClient);
+
+ SolrInputDocument doc = new SolrInputDocument();
+ doc.addField("id", "2");
+ doc.addField(fieldName, "val1");
+ UpdateRequest ureq = new UpdateRequest().add(doc);
+ cloudClient.request(ureq, collection);;
+ }
+
+ private void addStringField(String fieldName, String collection, CloudSolrClient cloudClient) throws IOException, SolrServerException {
+ Map fieldAttributes = new LinkedHashMap<>();
+ fieldAttributes.put("name", fieldName);
+ fieldAttributes.put("type", "string");
+ SchemaRequest.AddField addFieldUpdateSchemaRequest = new SchemaRequest.AddField(fieldAttributes);
+ SchemaResponse.UpdateResponse addFieldResponse = addFieldUpdateSchemaRequest.process(cloudClient, collection);
+ assertEquals(0, addFieldResponse.getStatus());
+ assertNull(addFieldResponse.getResponse().get("errors"));
+
+ log.info("added new field="+fieldName);
+ }
+
+}
diff --git a/solr/example/films/README.txt b/solr/example/films/README.txt
index 74a29a1ace0..f1fabe05a56 100644
--- a/solr/example/films/README.txt
+++ b/solr/example/films/README.txt
@@ -22,6 +22,7 @@ curl http://localhost:8983/solr/films/schema -X POST -H 'Content-type:applicatio
"add-field" : {
"name":"name",
"type":"text_general",
+ "multiValued":false,
"stored":true
},
"add-field" : {
@@ -103,6 +104,7 @@ curl http://localhost:8983/solr/films/schema -X POST -H 'Content-type:applicatio
"add-field" : {
"name":"name",
"type":"text_general",
+ "multiValued":false,
"stored":true
},
"add-field" : {