You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sh...@apache.org on 2012/12/21 14:11:16 UTC

svn commit: r1424907 - in /lucene/dev/branches/branch_4x: ./ solr/ solr/core/ solr/core/src/java/org/apache/solr/handler/loader/ solr/solrj/ solr/solrj/src/java/org/apache/solr/client/solrj/util/ solr/solrj/src/test/org/apache/solr/client/solrj/

Author: shalin
Date: Fri Dec 21 13:11:16 2012
New Revision: 1424907

URL: http://svn.apache.org/viewvc?rev=1424907&view=rev
Log:
SOLR-4134: Standard (XML) request writer cannot "set" multiple values into
  multivalued field with partial updates. (Luis Cappa Banda, Will Butler, shalin)

Modified:
    lucene/dev/branches/branch_4x/   (props changed)
    lucene/dev/branches/branch_4x/solr/   (props changed)
    lucene/dev/branches/branch_4x/solr/CHANGES.txt   (contents, props changed)
    lucene/dev/branches/branch_4x/solr/core/   (props changed)
    lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/loader/XMLLoader.java
    lucene/dev/branches/branch_4x/solr/solrj/   (props changed)
    lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java
    lucene/dev/branches/branch_4x/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java

Modified: lucene/dev/branches/branch_4x/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/CHANGES.txt?rev=1424907&r1=1424906&r2=1424907&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/CHANGES.txt (original)
+++ lucene/dev/branches/branch_4x/solr/CHANGES.txt Fri Dec 21 13:11:16 2012
@@ -369,6 +369,9 @@ Bug Fixes
 * SOLR-4213: Directories that are not shutdown until DirectoryFactory#close 
   do not have close listeners called on them. (Mark Miller)
 
+* SOLR-4134: Standard (XML) request writer cannot "set" multiple values into
+  multivalued field with partial updates. (Luis Cappa Banda, Will Butler, shalin)
+
 Other Changes
 ----------------------
 

Modified: lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/loader/XMLLoader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/loader/XMLLoader.java?rev=1424907&r1=1424906&r2=1424907&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/loader/XMLLoader.java (original)
+++ lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/loader/XMLLoader.java Fri Dec 21 13:11:16 2012
@@ -59,7 +59,9 @@ import javax.xml.parsers.SAXParserFactor
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 
@@ -379,8 +381,9 @@ public class XMLLoader extends ContentSt
     float boost = 1.0f;
     boolean isNull = false;
     String update = null;
-
-    while (true) {
+    Map<String, Map<String, List<Object>>> updateMap = null;
+    boolean complete = false;
+    while (!complete) {
       int event = parser.next();
       switch (event) {
         // Add everything to the text
@@ -392,13 +395,24 @@ public class XMLLoader extends ContentSt
 
         case XMLStreamConstants.END_ELEMENT:
           if ("doc".equals(parser.getLocalName())) {
-            return doc;
+            complete = true;
+            break;
           } else if ("field".equals(parser.getLocalName())) {
             Object v = isNull ? null : text.toString();
             if (update != null) {
-              Map<String,Object> extendedValue = new HashMap<String,Object>(1);
-              extendedValue.put(update, v);
-              v = extendedValue;
+              if (updateMap == null) updateMap = new HashMap<String, Map<String, List<Object>>>();
+              Map<String, List<Object>> extendedValues = updateMap.get(name);
+              if (extendedValues == null) {
+                extendedValues = new HashMap<String, List<Object>>(1);
+                updateMap.put(name, extendedValues);
+              }
+              List<Object> values = extendedValues.get(update);
+              if (values == null) {
+                values = new ArrayList<Object>();
+                extendedValues.put(update, values);
+              }
+              values.add(v);
+              break;
             }
             doc.addField(name, v, boost);
             boost = 1.0f;
@@ -434,5 +448,15 @@ public class XMLLoader extends ContentSt
           break;
       }
     }
+
+    if (updateMap != null)  {
+      for (Map.Entry<String, Map<String, List<Object>>> entry : updateMap.entrySet()) {
+        name = entry.getKey();
+        Map<String, List<Object>> value = entry.getValue();
+        doc.addField(name, value, 1.0f);
+      }
+    }
+
+    return doc;
   }
 }

Modified: lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java?rev=1424907&r1=1424906&r2=1424907&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java (original)
+++ lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java Fri Dec 21 13:11:16 2012
@@ -104,41 +104,53 @@ public class ClientUtils 
           // currently only supports a single value
           for (Entry<Object,Object> entry : ((Map<Object,Object>)v).entrySet()) {
             update = entry.getKey().toString();
-            Object fieldVal = entry.getValue();
-            v = fieldVal;
+            v = entry.getValue();
+            if (v instanceof Collection) {
+              Collection values = (Collection) v;
+              for (Object value : values) {
+                writeVal(writer, boost, name, value, update);
+                boost = 1.0f;
+              }
+            } else  {
+              writeVal(writer, boost, name, v, update);
+              boost = 1.0f;
+            }
           }
+        } else  {
+          writeVal(writer, boost, name, v, update);
+          // only write the boost for the first multi-valued field
+          // otherwise, the used boost is the product of all the boost values
+          boost = 1.0f;
         }
+      }
+    }
+    writer.write("</doc>");
+  }
 
-        if (v instanceof Date) {
-          v = DateUtil.getThreadLocalDateFormat().format( (Date)v );
-        } else if (v instanceof byte[]) {
-          byte[] bytes = (byte[]) v;
-          v = Base64.byteArrayToBase64(bytes, 0,bytes.length);
-        } else if (v instanceof ByteBuffer) {
-          ByteBuffer bytes = (ByteBuffer) v;
-          v = Base64.byteArrayToBase64(bytes.array(), bytes.position(),bytes.limit() - bytes.position());
-        }
-
-        if (update == null) {
-          if( boost != 1.0f ) {
-            XML.writeXML(writer, "field", v.toString(), "name", name, "boost", boost );
-          } else if (v != null) {
-            XML.writeXML(writer, "field", v.toString(), "name", name );
-          }
-        } else {
-          if( boost != 1.0f ) {
-            XML.writeXML(writer, "field", v.toString(), "name", name, "boost", boost, "update", update);
-          } else if (v != null) {
-            XML.writeXML(writer, "field", v.toString(), "name", name, "update", update);
-          }
-        }
+  private static void writeVal(Writer writer, float boost, String name, Object v, String update) throws IOException {
+    if (v instanceof Date) {
+      v = DateUtil.getThreadLocalDateFormat().format( (Date)v );
+    } else if (v instanceof byte[]) {
+      byte[] bytes = (byte[]) v;
+      v = Base64.byteArrayToBase64(bytes, 0, bytes.length);
+    } else if (v instanceof ByteBuffer) {
+      ByteBuffer bytes = (ByteBuffer) v;
+      v = Base64.byteArrayToBase64(bytes.array(), bytes.position(),bytes.limit() - bytes.position());
+    }
 
-        // only write the boost for the first multi-valued field
-        // otherwise, the used boost is the product of all the boost values
-        boost = 1.0f;
+    if (update == null) {
+      if( boost != 1.0f ) {
+        XML.writeXML(writer, "field", v.toString(), "name", name, "boost", boost);
+      } else if (v != null) {
+        XML.writeXML(writer, "field", v.toString(), "name", name );
+      }
+    } else {
+      if( boost != 1.0f ) {
+        XML.writeXML(writer, "field", v.toString(), "name", name, "boost", boost, "update", update);
+      } else if (v != null) {
+        XML.writeXML(writer, "field", v.toString(), "name", name, "update", update);
       }
     }
-    writer.write("</doc>");
   }
 
 

Modified: lucene/dev/branches/branch_4x/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java?rev=1424907&r1=1424906&r2=1424907&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java (original)
+++ lucene/dev/branches/branch_4x/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java Fri Dec 21 13:11:16 2012
@@ -19,14 +19,16 @@ package org.apache.solr.client.solrj;
 
 
 import java.io.IOException;
-import java.io.StringWriter;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Random;
 import java.util.concurrent.atomic.AtomicInteger;
+
+import com.google.common.collect.Lists;
 import junit.framework.Assert;
 
 import org.apache.lucene.util._TestUtil;
@@ -35,7 +37,6 @@ import org.apache.solr.client.solrj.impl
 import org.apache.solr.client.solrj.impl.ConcurrentUpdateSolrServer;
 import org.apache.solr.client.solrj.impl.HttpSolrServer;
 import org.apache.solr.client.solrj.impl.XMLResponseParser;
-import org.apache.solr.client.solrj.request.DirectXmlRequest;
 import org.apache.solr.client.solrj.request.LukeRequest;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.response.FieldStatsInfo;
@@ -53,7 +54,6 @@ import org.apache.solr.common.SolrDocume
 import org.apache.solr.common.SolrDocumentList;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrInputDocument;
-import org.apache.solr.common.util.XML;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.params.AnalysisParams;
 import org.apache.solr.common.params.CommonParams;
@@ -1380,6 +1380,36 @@ abstract public class SolrExampleTests e
     assertEquals("price was not updated?", 200.0f, resp.getResults().get(0).getFirstValue("price_f"));
     assertEquals("no name?", "gadget", resp.getResults().get(0).getFirstValue("name"));
   }
+
+  public void testUpdateMultiValuedField() throws Exception {
+    SolrServer solrServer = getSolrServer();
+    SolrInputDocument doc = new SolrInputDocument();
+    doc.addField("id", "123");
+    solrServer.add(doc);
+    solrServer.commit(true, true);
+    QueryResponse response = solrServer.query(new SolrQuery("id:123"));
+    assertEquals("Failed to add doc to cloud server", 1, response.getResults().getNumFound());
+
+    Map<String, List<String>> operation = new HashMap<String, List<String>>();
+    operation.put("set", Lists.asList("first", "second", new String[]{"third"}));
+    doc.addField("multi_ss", operation);
+    solrServer.add(doc);
+    solrServer.commit(true, true);
+    response = solrServer.query(new SolrQuery("id:123"));
+    assertTrue("Multi-valued field did not return a collection", response.getResults().get(0).get("multi_ss") instanceof List);
+    List<String> values = (List<String>) response.getResults().get(0).get("multi_ss");
+    assertEquals("Field values was not updated with all values via atomic update", 3, values.size());
+
+    operation.clear();
+    operation.put("add", Lists.asList("fourth", new String[]{"fifth"}));
+    doc.removeField("multi_ss");
+    doc.addField("multi_ss", operation);
+    solrServer.add(doc);
+    solrServer.commit(true, true);
+    response = solrServer.query(new SolrQuery("id:123"));
+    values = (List<String>) response.getResults().get(0).get("multi_ss");
+    assertEquals("Field values was not updated with all values via atomic update", 5, values.size());
+  }
   
   @Test
   public void testQueryWithParams() throws SolrServerException {