You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sa...@apache.org on 2016/11/15 00:30:02 UTC

[1/2] lucene-solr:master: SOLR-9751: PreAnalyzedField can cause managed schema corruption

Repository: lucene-solr
Updated Branches:
  refs/heads/branch_6x 375dd323a -> 8989c7747
  refs/heads/master c0b7edb5c -> 76b439a0b


SOLR-9751: PreAnalyzedField can cause managed schema corruption


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/76b439a0
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/76b439a0
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/76b439a0

Branch: refs/heads/master
Commit: 76b439a0bdf8a3e74f53130571535bbfdec5c771
Parents: c0b7edb
Author: Steve Rowe <sa...@apache.org>
Authored: Mon Nov 14 19:17:57 2016 -0500
Committer: Steve Rowe <sa...@apache.org>
Committed: Mon Nov 14 19:17:57 2016 -0500

----------------------------------------------------------------------
 solr/CHANGES.txt                                |  2 +
 .../java/org/apache/solr/schema/FieldType.java  | 20 ++++--
 .../solr/schema/FieldTypePluginLoader.java      | 59 ++++++++++------
 .../solr/schema/HasImplicitIndexAnalyzer.java   | 25 +++++++
 .../apache/solr/schema/PreAnalyzedField.java    |  2 +-
 .../conf/managed-schema                         | 41 +++++++++++
 .../conf/solrconfig.xml                         | 51 ++++++++++++++
 .../PreAnalyzedFieldManagedSchemaCloudTest.java | 73 ++++++++++++++++++++
 8 files changed, 243 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/76b439a0/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index f48b1ef..a4318b8 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -146,6 +146,8 @@ Bug Fixes
 * SOLR-9740: A bug in macro expansion of multi-valued parameters caused non-expanded values
   after the first expanded value in the same multi-valued parameter to be dropped.
   (Erik Hatcher, yonik)
+  
+* SOLR-9751: PreAnalyzedField can cause managed schema corruption. (Steve Rowe)
 
 
 Other Changes

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/76b439a0/solr/core/src/java/org/apache/solr/schema/FieldType.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/FieldType.java b/solr/core/src/java/org/apache/solr/schema/FieldType.java
index 8254bc3..ea4df90 100644
--- a/solr/core/src/java/org/apache/solr/schema/FieldType.java
+++ b/solr/core/src/java/org/apache/solr/schema/FieldType.java
@@ -864,13 +864,19 @@ public abstract class FieldType extends FieldProperties {
       namedPropertyValues.add(SIMILARITY, getSimilarityFactory().getNamedPropertyValues());
     }
     
-    if (isExplicitAnalyzer()) {
-      String analyzerProperty = isExplicitQueryAnalyzer() ? INDEX_ANALYZER : ANALYZER;
-      namedPropertyValues.add(analyzerProperty, getAnalyzerProperties(getIndexAnalyzer()));
-    } 
-    if (isExplicitQueryAnalyzer()) {
-      String analyzerProperty = isExplicitAnalyzer() ? QUERY_ANALYZER : ANALYZER;
-      namedPropertyValues.add(analyzerProperty, getAnalyzerProperties(getQueryAnalyzer()));
+    if (this instanceof HasImplicitIndexAnalyzer) {
+      if (isExplicitQueryAnalyzer()) {
+        namedPropertyValues.add(QUERY_ANALYZER, getAnalyzerProperties(getQueryAnalyzer()));
+      }
+    } else {
+      if (isExplicitAnalyzer()) {
+        String analyzerProperty = isExplicitQueryAnalyzer() ? INDEX_ANALYZER : ANALYZER;
+        namedPropertyValues.add(analyzerProperty, getAnalyzerProperties(getIndexAnalyzer()));
+      }
+      if (isExplicitQueryAnalyzer()) {
+        String analyzerProperty = isExplicitAnalyzer() ? QUERY_ANALYZER : ANALYZER;
+        namedPropertyValues.add(analyzerProperty, getAnalyzerProperties(getQueryAnalyzer()));
+      }
     }
     if (this instanceof TextField) {
       if (((TextField)this).isExplicitMultiTermAnalyzer()) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/76b439a0/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java b/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java
index f7e9b0e..f332934 100644
--- a/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java
+++ b/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java
@@ -110,31 +110,46 @@ public final class FieldTypePluginLoader
     if (null != simFactory) {
       ft.setSimilarity(simFactory);
     }
-    
-    if (null == queryAnalyzer) {
-      queryAnalyzer = analyzer;
-      ft.setIsExplicitQueryAnalyzer(false);
-    } else {
-      ft.setIsExplicitQueryAnalyzer(true);
-    }
-    if (null == analyzer) {
-      analyzer = queryAnalyzer;
+
+    if (ft instanceof HasImplicitIndexAnalyzer) {
       ft.setIsExplicitAnalyzer(false);
+      if (null != queryAnalyzer && null != analyzer) {
+        if (log.isWarnEnabled()) {
+          log.warn("Ignoring index-time analyzer for field: " + name);
+        }
+      } else if (null == queryAnalyzer) { // Accept non-query-time analyzer as a query-time analyzer 
+        queryAnalyzer = analyzer;
+      }
+      if (null != queryAnalyzer) {
+        ft.setIsExplicitQueryAnalyzer(true);
+        ft.setQueryAnalyzer(queryAnalyzer);
+      }
     } else {
-      ft.setIsExplicitAnalyzer(true);
-    }
-
-    if (null != analyzer) {
-      ft.setIndexAnalyzer(analyzer);
-      ft.setQueryAnalyzer(queryAnalyzer);
-      if (ft instanceof TextField) {
-        if (null == multiAnalyzer) {
-          multiAnalyzer = constructMultiTermAnalyzer(queryAnalyzer);
-          ((TextField)ft).setIsExplicitMultiTermAnalyzer(false);
-        } else {
-          ((TextField)ft).setIsExplicitMultiTermAnalyzer(true);
+      if (null == queryAnalyzer) {
+        queryAnalyzer = analyzer;
+        ft.setIsExplicitQueryAnalyzer(false);
+      } else {
+        ft.setIsExplicitQueryAnalyzer(true);
+      }
+      if (null == analyzer) {
+        analyzer = queryAnalyzer;
+        ft.setIsExplicitAnalyzer(false);
+      } else {
+        ft.setIsExplicitAnalyzer(true);
+      }
+  
+      if (null != analyzer) {
+        ft.setIndexAnalyzer(analyzer);
+        ft.setQueryAnalyzer(queryAnalyzer);
+        if (ft instanceof TextField) {
+          if (null == multiAnalyzer) {
+            multiAnalyzer = constructMultiTermAnalyzer(queryAnalyzer);
+            ((TextField)ft).setIsExplicitMultiTermAnalyzer(false);
+          } else {
+            ((TextField)ft).setIsExplicitMultiTermAnalyzer(true);
+          }
+          ((TextField)ft).setMultiTermAnalyzer(multiAnalyzer);
         }
-        ((TextField)ft).setMultiTermAnalyzer(multiAnalyzer);
       }
     }
     if (ft instanceof SchemaAware){

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/76b439a0/solr/core/src/java/org/apache/solr/schema/HasImplicitIndexAnalyzer.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/HasImplicitIndexAnalyzer.java b/solr/core/src/java/org/apache/solr/schema/HasImplicitIndexAnalyzer.java
new file mode 100644
index 0000000..9722852
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/schema/HasImplicitIndexAnalyzer.java
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.schema;
+
+/**
+ * Marker interface for field types that have an implicit (non-user-configurable)
+ * index-time schema.
+ */
+public interface HasImplicitIndexAnalyzer {
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/76b439a0/solr/core/src/java/org/apache/solr/schema/PreAnalyzedField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/PreAnalyzedField.java b/solr/core/src/java/org/apache/solr/schema/PreAnalyzedField.java
index 7bfed2b..87d4094 100644
--- a/solr/core/src/java/org/apache/solr/schema/PreAnalyzedField.java
+++ b/solr/core/src/java/org/apache/solr/schema/PreAnalyzedField.java
@@ -50,7 +50,7 @@ import static org.apache.solr.common.params.CommonParams.JSON;
  * Pre-analyzed field type provides a way to index a serialized token stream,
  * optionally with an independent stored value of a field.
  */
-public class PreAnalyzedField extends TextField {
+public class PreAnalyzedField extends TextField implements HasImplicitIndexAnalyzer {
   private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
   /** Init argument name. Value is a fully-qualified class name of the parser

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/76b439a0/solr/core/src/test-files/solr/configsets/cloud-managed-preanalyzed/conf/managed-schema
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/cloud-managed-preanalyzed/conf/managed-schema b/solr/core/src/test-files/solr/configsets/cloud-managed-preanalyzed/conf/managed-schema
new file mode 100644
index 0000000..e70e02b
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/cloud-managed-preanalyzed/conf/managed-schema
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ 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.
+-->
+<schema name="managed-preanalyzed" version="1.6">
+  <fieldType name="string" class="solr.StrField"/>
+  <fieldType name="int" class="solr.TrieIntField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+
+  <fieldType name="preanalyzed-no-analyzer" class="solr.PreAnalyzedField" parserImpl="json"/>
+  <fieldType name="preanalyzed-with-analyzer" class="solr.PreAnalyzedField">
+    <analyzer>
+      <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+    </analyzer>
+  </fieldType>
+  <fieldType name="preanalyzed-with-query-analyzer" class="solr.PreAnalyzedField">
+    <analyzer type="query">
+      <tokenizer class="solr.StandardTokenizerFactory"/>
+      <filter class="solr.LowerCaseFilterFactory"/>
+    </analyzer>
+  </fieldType>
+
+  <!-- for versioning -->
+  <field name="_version_" type="long" indexed="true" stored="true"/>
+  <field name="_root_" type="int" indexed="true" stored="true" multiValued="false" required="false"/>
+  <field name="id" type="string" indexed="true" stored="true"/>
+  <uniqueKey>id</uniqueKey>
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/76b439a0/solr/core/src/test-files/solr/configsets/cloud-managed-preanalyzed/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/cloud-managed-preanalyzed/conf/solrconfig.xml b/solr/core/src/test-files/solr/configsets/cloud-managed-preanalyzed/conf/solrconfig.xml
new file mode 100644
index 0000000..1beaf76
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/cloud-managed-preanalyzed/conf/solrconfig.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" ?>
+
+<!--
+ 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.
+-->
+
+<!-- Minimal solrconfig.xml with /select, /admin and /update only -->
+
+<config>
+
+  <dataDir>${solr.data.dir:}</dataDir>
+
+  <directoryFactory name="DirectoryFactory"
+                    class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"/>
+
+  <schemaFactory class="ManagedIndexSchemaFactory">
+    <bool name="mutable">${managed.schema.mutable:true}</bool>
+    <str name="managedSchemaResourceName">managed-schema</str>
+  </schemaFactory>
+
+  <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
+
+  <updateHandler class="solr.DirectUpdateHandler2">
+    <commitWithin>
+      <softCommit>${solr.commitwithin.softcommit:true}</softCommit>
+    </commitWithin>
+    <updateLog></updateLog>
+  </updateHandler>
+
+  <requestHandler name="/select" class="solr.SearchHandler">
+    <lst name="defaults">
+      <str name="echoParams">explicit</str>
+      <str name="indent">true</str>
+      <str name="df">text</str>
+    </lst>
+
+  </requestHandler>
+</config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/76b439a0/solr/core/src/test/org/apache/solr/schema/PreAnalyzedFieldManagedSchemaCloudTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/schema/PreAnalyzedFieldManagedSchemaCloudTest.java b/solr/core/src/test/org/apache/solr/schema/PreAnalyzedFieldManagedSchemaCloudTest.java
new file mode 100644
index 0000000..04e1be0
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/schema/PreAnalyzedFieldManagedSchemaCloudTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.schema;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.request.schema.SchemaRequest;
+import org.apache.solr.client.solrj.response.schema.SchemaResponse.FieldResponse;
+import org.apache.solr.client.solrj.response.schema.SchemaResponse.UpdateResponse;
+import org.apache.solr.cloud.SolrCloudTestCase;
+import org.apache.solr.common.cloud.DocCollection;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class PreAnalyzedFieldManagedSchemaCloudTest extends SolrCloudTestCase {
+
+  private static final String COLLECTION = "managed-preanalyzed";
+  private static final String CONFIG = "cloud-managed-preanalyzed";
+
+  @BeforeClass
+  public static void setupCluster() throws Exception {
+    configureCluster(2).addConfig(CONFIG, configset(CONFIG)).configure();
+    CollectionAdminRequest.createCollection(COLLECTION, CONFIG, 2, 1)
+        .setMaxShardsPerNode(1)
+        .process(cluster.getSolrClient());
+    cluster.getSolrClient().waitForState(COLLECTION, DEFAULT_TIMEOUT, TimeUnit.SECONDS,
+        (n, c) -> DocCollection.isFullyActive(n, c, 2, 1));
+  }
+
+  @Test
+  public void testAdd2Fields() throws Exception {
+    addField(keyValueArrayToMap("name", "field1", "type", "string"));
+    addField(keyValueArrayToMap("name", "field2", "type", "string"));
+  }
+
+  private void addField(Map<String,Object> field) throws Exception {
+    CloudSolrClient client = cluster.getSolrClient();
+    UpdateResponse addFieldResponse = new SchemaRequest.AddField(field).process(client, COLLECTION);
+    assertNotNull(addFieldResponse);
+    assertEquals(0, addFieldResponse.getStatus());
+    assertNull(addFieldResponse.getResponse().get("errors"));
+    FieldResponse fieldResponse = new SchemaRequest.Field(field.get("name").toString()).process(client, COLLECTION);
+    assertNotNull(fieldResponse);
+    assertEquals(0, fieldResponse.getStatus());
+  }
+
+  private Map<String,Object> keyValueArrayToMap(String... alternatingKeysAndValues) {
+    Map<String,Object> map = new HashMap<>();
+    for (int i = 0 ; i < alternatingKeysAndValues.length ; i += 2)
+      map.put(alternatingKeysAndValues[i], alternatingKeysAndValues[i + 1]);
+    return map;
+  }
+}
+


[2/2] lucene-solr:branch_6x: SOLR-9751: PreAnalyzedField can cause managed schema corruption

Posted by sa...@apache.org.
SOLR-9751: PreAnalyzedField can cause managed schema corruption


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/8989c774
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/8989c774
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/8989c774

Branch: refs/heads/branch_6x
Commit: 8989c774783a80cab6902e45f111cfe60ed15d49
Parents: 375dd32
Author: Steve Rowe <sa...@apache.org>
Authored: Mon Nov 14 19:17:57 2016 -0500
Committer: Steve Rowe <sa...@apache.org>
Committed: Mon Nov 14 19:18:23 2016 -0500

----------------------------------------------------------------------
 solr/CHANGES.txt                                |  2 +
 .../java/org/apache/solr/schema/FieldType.java  | 20 ++++--
 .../solr/schema/FieldTypePluginLoader.java      | 59 ++++++++++------
 .../solr/schema/HasImplicitIndexAnalyzer.java   | 25 +++++++
 .../apache/solr/schema/PreAnalyzedField.java    |  2 +-
 .../conf/managed-schema                         | 41 +++++++++++
 .../conf/solrconfig.xml                         | 51 ++++++++++++++
 .../PreAnalyzedFieldManagedSchemaCloudTest.java | 73 ++++++++++++++++++++
 8 files changed, 243 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8989c774/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 2ee215e..26beef7 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -93,6 +93,8 @@ Bug Fixes
 * SOLR-9740: A bug in macro expansion of multi-valued parameters caused non-expanded values
   after the first expanded value in the same multi-valued parameter to be dropped.
   (Erik Hatcher, yonik)
+  
+* SOLR-9751: PreAnalyzedField can cause managed schema corruption. (Steve Rowe)
 
 
 Other Changes

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8989c774/solr/core/src/java/org/apache/solr/schema/FieldType.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/FieldType.java b/solr/core/src/java/org/apache/solr/schema/FieldType.java
index 6556ddb..f3fdcba 100644
--- a/solr/core/src/java/org/apache/solr/schema/FieldType.java
+++ b/solr/core/src/java/org/apache/solr/schema/FieldType.java
@@ -879,13 +879,19 @@ public abstract class FieldType extends FieldProperties {
       namedPropertyValues.add(SIMILARITY, getSimilarityFactory().getNamedPropertyValues());
     }
     
-    if (isExplicitAnalyzer()) {
-      String analyzerProperty = isExplicitQueryAnalyzer() ? INDEX_ANALYZER : ANALYZER;
-      namedPropertyValues.add(analyzerProperty, getAnalyzerProperties(getIndexAnalyzer()));
-    } 
-    if (isExplicitQueryAnalyzer()) {
-      String analyzerProperty = isExplicitAnalyzer() ? QUERY_ANALYZER : ANALYZER;
-      namedPropertyValues.add(analyzerProperty, getAnalyzerProperties(getQueryAnalyzer()));
+    if (this instanceof HasImplicitIndexAnalyzer) {
+      if (isExplicitQueryAnalyzer()) {
+        namedPropertyValues.add(QUERY_ANALYZER, getAnalyzerProperties(getQueryAnalyzer()));
+      }
+    } else {
+      if (isExplicitAnalyzer()) {
+        String analyzerProperty = isExplicitQueryAnalyzer() ? INDEX_ANALYZER : ANALYZER;
+        namedPropertyValues.add(analyzerProperty, getAnalyzerProperties(getIndexAnalyzer()));
+      }
+      if (isExplicitQueryAnalyzer()) {
+        String analyzerProperty = isExplicitAnalyzer() ? QUERY_ANALYZER : ANALYZER;
+        namedPropertyValues.add(analyzerProperty, getAnalyzerProperties(getQueryAnalyzer()));
+      }
     }
     if (this instanceof TextField) {
       if (((TextField)this).isExplicitMultiTermAnalyzer()) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8989c774/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java b/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java
index f7e9b0e..f332934 100644
--- a/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java
+++ b/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java
@@ -110,31 +110,46 @@ public final class FieldTypePluginLoader
     if (null != simFactory) {
       ft.setSimilarity(simFactory);
     }
-    
-    if (null == queryAnalyzer) {
-      queryAnalyzer = analyzer;
-      ft.setIsExplicitQueryAnalyzer(false);
-    } else {
-      ft.setIsExplicitQueryAnalyzer(true);
-    }
-    if (null == analyzer) {
-      analyzer = queryAnalyzer;
+
+    if (ft instanceof HasImplicitIndexAnalyzer) {
       ft.setIsExplicitAnalyzer(false);
+      if (null != queryAnalyzer && null != analyzer) {
+        if (log.isWarnEnabled()) {
+          log.warn("Ignoring index-time analyzer for field: " + name);
+        }
+      } else if (null == queryAnalyzer) { // Accept non-query-time analyzer as a query-time analyzer 
+        queryAnalyzer = analyzer;
+      }
+      if (null != queryAnalyzer) {
+        ft.setIsExplicitQueryAnalyzer(true);
+        ft.setQueryAnalyzer(queryAnalyzer);
+      }
     } else {
-      ft.setIsExplicitAnalyzer(true);
-    }
-
-    if (null != analyzer) {
-      ft.setIndexAnalyzer(analyzer);
-      ft.setQueryAnalyzer(queryAnalyzer);
-      if (ft instanceof TextField) {
-        if (null == multiAnalyzer) {
-          multiAnalyzer = constructMultiTermAnalyzer(queryAnalyzer);
-          ((TextField)ft).setIsExplicitMultiTermAnalyzer(false);
-        } else {
-          ((TextField)ft).setIsExplicitMultiTermAnalyzer(true);
+      if (null == queryAnalyzer) {
+        queryAnalyzer = analyzer;
+        ft.setIsExplicitQueryAnalyzer(false);
+      } else {
+        ft.setIsExplicitQueryAnalyzer(true);
+      }
+      if (null == analyzer) {
+        analyzer = queryAnalyzer;
+        ft.setIsExplicitAnalyzer(false);
+      } else {
+        ft.setIsExplicitAnalyzer(true);
+      }
+  
+      if (null != analyzer) {
+        ft.setIndexAnalyzer(analyzer);
+        ft.setQueryAnalyzer(queryAnalyzer);
+        if (ft instanceof TextField) {
+          if (null == multiAnalyzer) {
+            multiAnalyzer = constructMultiTermAnalyzer(queryAnalyzer);
+            ((TextField)ft).setIsExplicitMultiTermAnalyzer(false);
+          } else {
+            ((TextField)ft).setIsExplicitMultiTermAnalyzer(true);
+          }
+          ((TextField)ft).setMultiTermAnalyzer(multiAnalyzer);
         }
-        ((TextField)ft).setMultiTermAnalyzer(multiAnalyzer);
       }
     }
     if (ft instanceof SchemaAware){

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8989c774/solr/core/src/java/org/apache/solr/schema/HasImplicitIndexAnalyzer.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/HasImplicitIndexAnalyzer.java b/solr/core/src/java/org/apache/solr/schema/HasImplicitIndexAnalyzer.java
new file mode 100644
index 0000000..9722852
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/schema/HasImplicitIndexAnalyzer.java
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.schema;
+
+/**
+ * Marker interface for field types that have an implicit (non-user-configurable)
+ * index-time schema.
+ */
+public interface HasImplicitIndexAnalyzer {
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8989c774/solr/core/src/java/org/apache/solr/schema/PreAnalyzedField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/PreAnalyzedField.java b/solr/core/src/java/org/apache/solr/schema/PreAnalyzedField.java
index 09d3590..6fdb457 100644
--- a/solr/core/src/java/org/apache/solr/schema/PreAnalyzedField.java
+++ b/solr/core/src/java/org/apache/solr/schema/PreAnalyzedField.java
@@ -50,7 +50,7 @@ import static org.apache.solr.common.params.CommonParams.JSON;
  * Pre-analyzed field type provides a way to index a serialized token stream,
  * optionally with an independent stored value of a field.
  */
-public class PreAnalyzedField extends TextField {
+public class PreAnalyzedField extends TextField implements HasImplicitIndexAnalyzer {
   private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
   /** Init argument name. Value is a fully-qualified class name of the parser

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8989c774/solr/core/src/test-files/solr/configsets/cloud-managed-preanalyzed/conf/managed-schema
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/cloud-managed-preanalyzed/conf/managed-schema b/solr/core/src/test-files/solr/configsets/cloud-managed-preanalyzed/conf/managed-schema
new file mode 100644
index 0000000..e70e02b
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/cloud-managed-preanalyzed/conf/managed-schema
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ 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.
+-->
+<schema name="managed-preanalyzed" version="1.6">
+  <fieldType name="string" class="solr.StrField"/>
+  <fieldType name="int" class="solr.TrieIntField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+
+  <fieldType name="preanalyzed-no-analyzer" class="solr.PreAnalyzedField" parserImpl="json"/>
+  <fieldType name="preanalyzed-with-analyzer" class="solr.PreAnalyzedField">
+    <analyzer>
+      <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+    </analyzer>
+  </fieldType>
+  <fieldType name="preanalyzed-with-query-analyzer" class="solr.PreAnalyzedField">
+    <analyzer type="query">
+      <tokenizer class="solr.StandardTokenizerFactory"/>
+      <filter class="solr.LowerCaseFilterFactory"/>
+    </analyzer>
+  </fieldType>
+
+  <!-- for versioning -->
+  <field name="_version_" type="long" indexed="true" stored="true"/>
+  <field name="_root_" type="int" indexed="true" stored="true" multiValued="false" required="false"/>
+  <field name="id" type="string" indexed="true" stored="true"/>
+  <uniqueKey>id</uniqueKey>
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8989c774/solr/core/src/test-files/solr/configsets/cloud-managed-preanalyzed/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/cloud-managed-preanalyzed/conf/solrconfig.xml b/solr/core/src/test-files/solr/configsets/cloud-managed-preanalyzed/conf/solrconfig.xml
new file mode 100644
index 0000000..1beaf76
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/cloud-managed-preanalyzed/conf/solrconfig.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" ?>
+
+<!--
+ 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.
+-->
+
+<!-- Minimal solrconfig.xml with /select, /admin and /update only -->
+
+<config>
+
+  <dataDir>${solr.data.dir:}</dataDir>
+
+  <directoryFactory name="DirectoryFactory"
+                    class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"/>
+
+  <schemaFactory class="ManagedIndexSchemaFactory">
+    <bool name="mutable">${managed.schema.mutable:true}</bool>
+    <str name="managedSchemaResourceName">managed-schema</str>
+  </schemaFactory>
+
+  <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
+
+  <updateHandler class="solr.DirectUpdateHandler2">
+    <commitWithin>
+      <softCommit>${solr.commitwithin.softcommit:true}</softCommit>
+    </commitWithin>
+    <updateLog></updateLog>
+  </updateHandler>
+
+  <requestHandler name="/select" class="solr.SearchHandler">
+    <lst name="defaults">
+      <str name="echoParams">explicit</str>
+      <str name="indent">true</str>
+      <str name="df">text</str>
+    </lst>
+
+  </requestHandler>
+</config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8989c774/solr/core/src/test/org/apache/solr/schema/PreAnalyzedFieldManagedSchemaCloudTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/schema/PreAnalyzedFieldManagedSchemaCloudTest.java b/solr/core/src/test/org/apache/solr/schema/PreAnalyzedFieldManagedSchemaCloudTest.java
new file mode 100644
index 0000000..04e1be0
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/schema/PreAnalyzedFieldManagedSchemaCloudTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.schema;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.request.schema.SchemaRequest;
+import org.apache.solr.client.solrj.response.schema.SchemaResponse.FieldResponse;
+import org.apache.solr.client.solrj.response.schema.SchemaResponse.UpdateResponse;
+import org.apache.solr.cloud.SolrCloudTestCase;
+import org.apache.solr.common.cloud.DocCollection;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class PreAnalyzedFieldManagedSchemaCloudTest extends SolrCloudTestCase {
+
+  private static final String COLLECTION = "managed-preanalyzed";
+  private static final String CONFIG = "cloud-managed-preanalyzed";
+
+  @BeforeClass
+  public static void setupCluster() throws Exception {
+    configureCluster(2).addConfig(CONFIG, configset(CONFIG)).configure();
+    CollectionAdminRequest.createCollection(COLLECTION, CONFIG, 2, 1)
+        .setMaxShardsPerNode(1)
+        .process(cluster.getSolrClient());
+    cluster.getSolrClient().waitForState(COLLECTION, DEFAULT_TIMEOUT, TimeUnit.SECONDS,
+        (n, c) -> DocCollection.isFullyActive(n, c, 2, 1));
+  }
+
+  @Test
+  public void testAdd2Fields() throws Exception {
+    addField(keyValueArrayToMap("name", "field1", "type", "string"));
+    addField(keyValueArrayToMap("name", "field2", "type", "string"));
+  }
+
+  private void addField(Map<String,Object> field) throws Exception {
+    CloudSolrClient client = cluster.getSolrClient();
+    UpdateResponse addFieldResponse = new SchemaRequest.AddField(field).process(client, COLLECTION);
+    assertNotNull(addFieldResponse);
+    assertEquals(0, addFieldResponse.getStatus());
+    assertNull(addFieldResponse.getResponse().get("errors"));
+    FieldResponse fieldResponse = new SchemaRequest.Field(field.get("name").toString()).process(client, COLLECTION);
+    assertNotNull(fieldResponse);
+    assertEquals(0, fieldResponse.getStatus());
+  }
+
+  private Map<String,Object> keyValueArrayToMap(String... alternatingKeysAndValues) {
+    Map<String,Object> map = new HashMap<>();
+    for (int i = 0 ; i < alternatingKeysAndValues.length ; i += 2)
+      map.put(alternatingKeysAndValues[i], alternatingKeysAndValues[i + 1]);
+    return map;
+  }
+}
+