You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ho...@apache.org on 2014/03/05 19:05:26 UTC

svn commit: r1574595 - in /lucene/dev/trunk: lucene/ lucene/core/src/java/org/apache/lucene/index/ lucene/core/src/test/org/apache/lucene/index/ solr/ solr/core/src/test-files/solr/collection1/conf/ solr/core/src/test/org/apache/solr/update/

Author: hossman
Date: Wed Mar  5 18:05:25 2014
New Revision: 1574595

URL: http://svn.apache.org/r1574595
Log:
LUCENE-5472: IndexWriter.addDocument will now throw an IllegalArgumentException if a Term to be indexed exceeds IndexWriter.MAX_TERM_LENGTH

Added:
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestExceedMaxTermLength.java   (with props)
    lucene/dev/trunk/solr/core/src/test/org/apache/solr/update/TestExceedMaxTermLength.java   (with props)
Modified:
    lucene/dev/trunk/lucene/CHANGES.txt
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/DocFieldProcessor.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/DocInverterPerField.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/TermsHashPerField.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java
    lucene/dev/trunk/solr/CHANGES.txt
    lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema11.xml

Modified: lucene/dev/trunk/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/CHANGES.txt?rev=1574595&r1=1574594&r2=1574595&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/CHANGES.txt (original)
+++ lucene/dev/trunk/lucene/CHANGES.txt Wed Mar  5 18:05:25 2014
@@ -68,6 +68,13 @@ Optimizations
 
 ======================= Lucene 4.8.0 =======================
 
+Changes in Runtime Behavior
+
+* LUCENE-5472: IndexWriter.addDocument will now throw an IllegalArgumentException 
+  if a Term to be indexed exceeds IndexWriter.MAX_TERM_LENGTH.  To recreate previous
+  behavior of silently ignoring these terms, use LengthFilter in your Analyzer.
+  (hossman, Mike McCandless, Varun Thacker)
+
 New Features
 
 * LUCENE-5454: Add SortedSetSortField to lucene/sandbox, to allow sorting

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/DocFieldProcessor.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/DocFieldProcessor.java?rev=1574595&r1=1574594&r2=1574595&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/DocFieldProcessor.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/DocFieldProcessor.java Wed Mar  5 18:05:25 2014
@@ -209,11 +209,6 @@ final class DocFieldProcessor extends Do
       final DocFieldProcessorPerField perField = fields[i];
       perField.consumer.processFields(perField.fields, perField.fieldCount);
     }
-
-    if (docState.maxTermPrefix != null && docState.infoStream.isEnabled("IW")) {
-      docState.infoStream.message("IW", "WARNING: document contains at least one immense term (whose UTF8 encoding is longer than the max length " + DocumentsWriterPerThread.MAX_TERM_LENGTH_UTF8 + "), all of which were skipped.  Please correct the analyzer to not produce such terms.  The prefix of the first immense term is: '" + docState.maxTermPrefix + "...'");
-      docState.maxTermPrefix = null;
-    }
   }
 
   private DocFieldProcessorPerField processField(FieldInfos.Builder fieldInfos,

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/DocInverterPerField.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/DocInverterPerField.java?rev=1574595&r1=1574594&r2=1574595&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/DocInverterPerField.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/DocInverterPerField.java Wed Mar  5 18:05:25 2014
@@ -23,7 +23,6 @@ import org.apache.lucene.analysis.TokenS
 import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
-import org.apache.lucene.util.IOUtils;
 
 /**
  * Holds state for inverting all occurrences of a single
@@ -182,6 +181,17 @@ final class DocInverterPerField extends 
           // when we come back around to the field...
           fieldState.position += posIncrAttribute.getPositionIncrement();
           fieldState.offset += offsetAttribute.endOffset();
+
+
+          if (docState.maxTermPrefix != null) {
+            final String msg = "Document contains at least one immense term in field=\"" + fieldInfo.name + "\" (whose UTF8 encoding is longer than the max length " + DocumentsWriterPerThread.MAX_TERM_LENGTH_UTF8 + "), all of which were skipped.  Please correct the analyzer to not produce such terms.  The prefix of the first immense term is: '" + docState.maxTermPrefix + "...'";
+            if (docState.infoStream.isEnabled("IW")) {
+              docState.infoStream.message("IW", "ERROR: " + msg);
+            }
+            docState.maxTermPrefix = null;
+            throw new IllegalArgumentException(msg);
+          }
+
           /* if success was false above there is an exception coming through and we won't get here.*/
           succeededInProcessingField = true;
         } finally {

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java?rev=1574595&r1=1574594&r2=1574595&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java Wed Mar  5 18:05:25 2014
@@ -207,8 +207,9 @@ public class IndexWriter implements Clos
   /**
    * Absolute hard maximum length for a term, in bytes once
    * encoded as UTF8.  If a term arrives from the analyzer
-   * longer than this length, it is skipped and a message is
-   * printed to infoStream, if set (see {@link
+   * longer than this length, an
+   * <code>IllegalArgumentException</code>  is thrown
+   * and a message is printed to infoStream, if set (see {@link
    * IndexWriterConfig#setInfoStream(InfoStream)}).
    */
   public final static int MAX_TERM_LENGTH = DocumentsWriterPerThread.MAX_TERM_LENGTH_UTF8;
@@ -1159,7 +1160,7 @@ public class IndexWriter implements Clos
    * merge policy.
    *
    * <p>Note that each term in the document can be no longer
-   * than 16383 characters, otherwise an
+   * than {@link #MAX_TERM_LENGTH} in bytes, otherwise an
    * IllegalArgumentException will be thrown.</p>
    *
    * <p>Note that it's possible to create an invalid Unicode

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/TermsHashPerField.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/TermsHashPerField.java?rev=1574595&r1=1574594&r2=1574595&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/TermsHashPerField.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/TermsHashPerField.java Wed Mar  5 18:05:25 2014
@@ -179,12 +179,11 @@ final class TermsHashPerField extends In
     try {
       termID = bytesHash.add(termBytesRef, termAtt.fillBytesRef());
     } catch (MaxBytesLengthExceededException e) {
-      // Not enough room in current block
-      // Just skip this term, to remain as robust as
-      // possible during indexing.  A TokenFilter
-      // can be inserted into the analyzer chain if
-      // other behavior is wanted (pruning the term
-      // to a prefix, throwing an exception, etc).
+      // Term is too large; record this here (can't throw an
+      // exc because DocInverterPerField will then abort the
+      // entire segment) and then throw an exc later in
+      // DocInverterPerField.java.  LengthFilter can always be
+      // used to prune the term before indexing:
       if (docState.maxTermPrefix == null) {
         final int saved = termBytesRef.length;
         try {

Added: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestExceedMaxTermLength.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestExceedMaxTermLength.java?rev=1574595&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestExceedMaxTermLength.java (added)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestExceedMaxTermLength.java Wed Mar  5 18:05:25 2014
@@ -0,0 +1,105 @@
+package org.apache.lucene.index;
+
+/*
+ * 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.
+ */
+
+import org.apache.lucene.analysis.MockAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util.TestUtil;
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.After;
+
+/**
+ * Tests that a useful exception is thrown when attempting to index a term that is 
+ * too large
+ *
+ * @see IndexWriter#MAX_TERM_LENGTH
+ */
+public class TestExceedMaxTermLength extends LuceneTestCase {
+
+  private final static int minTestTermLength = IndexWriter.MAX_TERM_LENGTH + 1;
+  private final static int maxTestTermLegnth = IndexWriter.MAX_TERM_LENGTH * 2;
+
+  Directory dir = null;
+
+  @Before
+  public void createDir() {
+    dir = newDirectory();
+  }
+  @After
+  public void destroyDir() throws IOException {
+    dir.close();
+    dir = null;
+  }
+
+  public void test() throws Exception {
+    
+    IndexWriter w = new IndexWriter
+      (dir, newIndexWriterConfig(random(), 
+                                 TEST_VERSION_CURRENT,
+                                 new MockAnalyzer(random())));
+    try {
+      final FieldType ft = new FieldType();
+      ft.setIndexed(true);
+      ft.setStored(random().nextBoolean());
+      ft.freeze();
+      
+      final Document doc = new Document();
+      if (random().nextBoolean()) {
+        // totally ok short field value
+        doc.add(new Field(TestUtil.randomSimpleString(random(), 1, 10),
+                          TestUtil.randomSimpleString(random(), 1, 10),
+                          ft));
+      }
+      // problematic field
+      final String name = TestUtil.randomSimpleString(random(), 1, 50);
+      final String value = TestUtil.randomSimpleString(random(),
+                                                       minTestTermLength,
+                                                       maxTestTermLegnth);
+      final Field f = new Field(name, value, ft);
+      if (random().nextBoolean()) {
+        // totally ok short field value
+        doc.add(new Field(TestUtil.randomSimpleString(random(), 1, 10),
+                          TestUtil.randomSimpleString(random(), 1, 10),
+                          ft));
+      }
+      doc.add(f);
+      
+      try {
+        w.addDocument(doc);
+        fail("Did not get an exception from adding a monster term");
+      } catch (IllegalArgumentException e) {
+        final String maxLengthMsg = String.valueOf(IndexWriter.MAX_TERM_LENGTH);
+        final String msg = e.getMessage();
+        assertTrue("IllegalArgumentException didn't mention 'immense term': " + msg,
+                   msg.contains("immense term"));
+        assertTrue("IllegalArgumentException didn't mention max length ("+maxLengthMsg+"): " + msg,
+                   msg.contains(maxLengthMsg));
+        assertTrue("IllegalArgumentException didn't mention field name ("+name+"): " + msg,
+                   msg.contains(name));
+      }
+    } finally {
+      w.close();
+    }
+  }
+}

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java?rev=1574595&r1=1574594&r2=1574595&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java Wed Mar  5 18:05:25 2014
@@ -1660,32 +1660,32 @@ public class TestIndexWriter extends Luc
     // This contents produces a too-long term:
     String contents = "abc xyz x" + bigTerm + " another term";
     doc.add(new TextField("content", contents, Field.Store.NO));
-    w.addDocument(doc);
+    try {
+      w.addDocument(doc);
+      fail("should have hit exception");
+    } catch (IllegalArgumentException iae) {
+      // expected
+    }
 
     // Make sure we can add another normal document
     doc = new Document();
     doc.add(new TextField("content", "abc bbb ccc", Field.Store.NO));
     w.addDocument(doc);
 
+    // So we remove the deleted doc:
+    w.forceMerge(1);
+
     IndexReader reader = w.getReader();
     w.close();
 
     // Make sure all terms < max size were indexed
-    assertEquals(2, reader.docFreq(new Term("content", "abc")));
+    assertEquals(1, reader.docFreq(new Term("content", "abc")));
     assertEquals(1, reader.docFreq(new Term("content", "bbb")));
-    assertEquals(1, reader.docFreq(new Term("content", "term")));
-    assertEquals(1, reader.docFreq(new Term("content", "another")));
-
-    // Make sure position is still incremented when
-    // massive term is skipped:
-    DocsAndPositionsEnum tps = MultiFields.getTermPositionsEnum(reader, null, "content", new BytesRef("another"));
-    assertEquals(0, tps.nextDoc());
-    assertEquals(1, tps.freq());
-    assertEquals(3, tps.nextPosition());
+    assertEquals(0, reader.docFreq(new Term("content", "term")));
 
-    // Make sure the doc that has the massive term is in
+    // Make sure the doc that has the massive term is NOT in
     // the index:
-    assertEquals("document with wicked long term should is not in the index!", 2, reader.numDocs());
+    assertEquals("document with wicked long term is in the index!", 1, reader.numDocs());
 
     reader.close();
     dir.close();

Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1574595&r1=1574594&r2=1574595&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Wed Mar  5 18:05:25 2014
@@ -76,7 +76,16 @@ Velocity 1.7 and Velocity Tools 2.0
 Apache UIMA 2.3.1
 Apache ZooKeeper 3.4.5
 
-                      
+Upgrading from Solr 4.7
+----------------------
+
+* In previous versions of Solr, Terms that exceeded Lucene's MAX_TERM_LENGTH were
+  silently ignored when indexing documents.  Begining with Solr 4.8, a document
+  an error will be generated when attempting to index a document with a term
+  that is too large.  If you wish to continue to have large terms ignored,
+  use "solr.LengthFilterFactory" in all of your Analyzers.  See LUCENE-5472 for
+  more details.
+
 Detailed Change List
 ----------------------
 
@@ -154,6 +163,11 @@ Other Changes
   registration exists, wait a short time to see if it goes away.
   (Mark Miller)
 
+* LUCENE-5472: IndexWriter.addDocument will now throw an IllegalArgumentException 
+  if a Term to be indexed exceeds IndexWriter.MAX_TERM_LENGTH.  To recreate previous
+  behavior of silently ignoring these terms, use LengthFilter in your Analyzer.
+  (hossman, Mike McCandless, Varun Thacker)
+
 ==================  4.7.0 ==================
 
 Versions of Major Components

Modified: lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema11.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema11.xml?rev=1574595&r1=1574594&r2=1574595&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema11.xml (original)
+++ lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema11.xml Wed Mar  5 18:05:25 2014
@@ -287,6 +287,16 @@ valued. -->
                class="solr.ExternalFileField"/>
 
     <fieldType name="text_no_analyzer" stored="false" indexed="true" class="solr.TextField" />
+
+    <fieldtype name="text_length" class="solr.TextField">
+      <analyzer>
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.StandardFilterFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.LengthFilterFactory" min="2" max="32768"/>
+      </analyzer>
+    </fieldtype>  
+
  </types>
 
 
@@ -324,6 +334,9 @@ valued. -->
 
    <field name="_version_" type="long" indexed="true" stored="true" multiValued="false" />
 
+   <field name="cat" type="string" indexed="true" stored="true" multiValued="true"/>
+   <field name="cat_length" type="text_length" indexed="true" stored="true" multiValued="true"/>   
+
    <!-- Dynamic field definitions.  If a field name is not found, dynamicFields
         will be used if the name matches any of the patterns.
         RESTRICTION: the glob-like pattern in the name attribute must have

Added: lucene/dev/trunk/solr/core/src/test/org/apache/solr/update/TestExceedMaxTermLength.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/update/TestExceedMaxTermLength.java?rev=1574595&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/update/TestExceedMaxTermLength.java (added)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/update/TestExceedMaxTermLength.java Wed Mar  5 18:05:25 2014
@@ -0,0 +1,153 @@
+package org.apache.solr.update;
+
+/*
+ * 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.
+ */
+
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.util.TestUtil;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.SolrTestCaseJ4;
+
+import java.util.Locale;
+
+import org.junit.After;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestExceedMaxTermLength extends SolrTestCaseJ4 {
+
+  public final static String TEST_SOLRCONFIG_NAME = "solrconfig.xml";
+  public final static String TEST_SCHEMAXML_NAME = "schema11.xml";
+
+  private final static int minTestTermLength = IndexWriter.MAX_TERM_LENGTH + 1;
+  private final static int maxTestTermLegnth = IndexWriter.MAX_TERM_LENGTH * 2;
+
+  @BeforeClass
+  public static void beforeTests() throws Exception {
+    initCore(TEST_SOLRCONFIG_NAME, TEST_SCHEMAXML_NAME);
+  }
+
+  @After
+  public void cleanup() throws Exception {
+    assertU(delQ("*:*"));
+    assertU(commit());
+  }
+
+  @Test
+  public void testExceededMaxTermLength(){
+
+    // problematic field
+    final String longFieldName = "cat";
+    final String longFieldValue = TestUtil.randomSimpleString(random(),
+        minTestTermLength,
+        maxTestTermLegnth);
+
+    final String okayFieldName = TestUtil.randomSimpleString(random(), 1, 50) + "_sS" ; //Dynamic field
+    final String okayFieldValue = TestUtil.randomSimpleString(random(),
+        minTestTermLength,
+        maxTestTermLegnth);
+
+    boolean includeOkayFields = random().nextBoolean();
+
+    if(random().nextBoolean()) {
+      //Use XML
+      String doc;
+      if(includeOkayFields) {
+        doc = adoc("id", "1", longFieldName, longFieldValue, okayFieldName, okayFieldValue);
+      } else {
+        doc = adoc("id", "1", longFieldName, longFieldValue);
+      }
+      assertFailedU(doc);
+    } else {
+      //Use JSON
+      try {
+        if(includeOkayFields) {
+          String jsonStr = "[{'id':'1','%s':'%s', '%s': '%s'}]";
+          jsonStr = String.format(Locale.ROOT, jsonStr, longFieldName, longFieldValue, 
+                                  okayFieldName, okayFieldValue);
+          updateJ(json(jsonStr), null);
+        } else {
+          String jsonStr = "[{'id':'1','%s':'%s'}]";
+          jsonStr = String.format(Locale.ROOT, jsonStr, longFieldName, longFieldValue);
+          updateJ(json(jsonStr), null);
+        }
+      } catch (Exception e) {
+        //expected
+        String msg= e.getCause().getMessage();
+        assertTrue(msg.contains("one immense term in field=\"cat\""));
+      }
+
+    }
+
+    assertU(commit());
+
+    assertQ(req("q", "*:*"), "//*[@numFound='0']");
+  }
+
+  @Test
+  public void testExceededMaxTermLengthWithLimitingFilter(){
+
+    // problematic field
+    final String longFieldName = "cat_length";
+    final String longFieldValue = TestUtil.randomSimpleString(random(),
+        minTestTermLength,
+        maxTestTermLegnth);
+
+    final String okayFieldName = TestUtil.randomSimpleString(random(), 1, 50) + "_sS" ; //Dynamic field
+    final String okayFieldValue = TestUtil.randomSimpleString(random(),
+        minTestTermLength,
+        maxTestTermLegnth);
+
+    boolean includeOkayFields = random().nextBoolean();
+
+    if(random().nextBoolean()) {
+      //Use XML
+      String doc;
+      if(includeOkayFields) {
+        doc = adoc("id", "1", longFieldName, longFieldValue, okayFieldName, okayFieldValue);
+      } else {
+        doc = adoc("id", "1", longFieldName, longFieldValue);
+      }
+      assertU(doc);
+    } else {
+      //Use JSON
+      String jsonStr = null;
+      try {
+        if(includeOkayFields) {
+          jsonStr = "[{'id':'1','%s':'%s', '%s': '%s'}]";
+          jsonStr = String.format(Locale.ROOT, jsonStr, longFieldName, longFieldValue, 
+                                  okayFieldName, okayFieldValue);
+          updateJ(json(jsonStr), null);
+        } else {
+          jsonStr = "[{'id':'1','%s':'%s'}]";
+          jsonStr = String.format(Locale.ROOT, jsonStr, longFieldName, longFieldValue);
+          updateJ(json(jsonStr), null);
+        }
+      } catch (Exception e) {
+        //expected
+        fail("Should not have failed adding doc " + jsonStr);
+        String msg= e.getCause().getMessage();
+        assertTrue(msg.contains("one immense term in field=\"cat\""));
+      }
+
+    }
+
+    assertU(commit());
+
+    assertQ(req("q", "*:*"), "//*[@numFound='1']");
+  }
+}