This is an automated email from the ASF dual-hosted git repository.

dsmiley pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/branch_9x by this push:
     new 3b2a3a22e34 SOLR-17669: SolrJ getBeans: reduce memory for 
dynamic/wildcard Field annotated methods (#3179)
3b2a3a22e34 is described below

commit 3b2a3a22e344f4fce60edc2a98321b5a6b9af3ea
Author: Martin Anzinger <[email protected]>
AuthorDate: Tue Feb 25 23:50:40 2025 +0100

    SOLR-17669: SolrJ getBeans: reduce memory for dynamic/wildcard Field 
annotated methods (#3179)
    
    Reduce memory Consumption by 80-90% as found by one user.  Might increase 
matching performance as well.
    
    (cherry picked from commit 5ddaf5f9d95f86913c6fe0924cd5d9b13fdb456c)
---
 solr/CHANGES.txt                                   |  2 ++
 .../client/solrj/beans/DocumentObjectBinder.java   | 26 ++++++++++++++-----
 .../solrj/beans/TestDocumentObjectBinder.java      | 29 ++++++++++++++++++++++
 3 files changed, 51 insertions(+), 6 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 1a6269e8f2e..28f0a7eba80 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -35,6 +35,8 @@ Optimizations
 ---------------------
 * SOLR-17578: Remove ZkController internal core supplier, for slightly faster 
reconnection after Zookeeper session loss. (Pierre Salagnac)
 
+* SOLR-17669: Reduced memory usage in SolrJ getBeans() method when handling 
dynamic fields with wildcards. (Martin Anzinger)
+
 Bug Fixes
 ---------------------
 * SOLR-17587: Metrics: wt=prometheus fix for non-compliant exposition format 
containing duplicate TYPE lines.
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/beans/DocumentObjectBinder.java
 
b/solr/solrj/src/java/org/apache/solr/client/solrj/beans/DocumentObjectBinder.java
index d0f65eeb354..caf34ab2b7d 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/beans/DocumentObjectBinder.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/beans/DocumentObjectBinder.java
@@ -186,7 +186,7 @@ public class DocumentObjectBinder {
      * is set to <code>TRUE</code> as well as <code>isList</code> is set to 
<code>TRUE</code>
      */
     private boolean isContainedInMap;
-    private Pattern dynamicFieldNamePatternMatcher;
+    private java.util.function.Predicate<String> 
dynamicFieldNamePatternMatcher;
 
     public DocField(AccessibleObject member) {
       if (member instanceof java.lang.reflect.Field) {
@@ -235,10 +235,24 @@ public class DocumentObjectBinder {
       } else if (annotation.value().indexOf('*') >= 0) {
         // dynamic fields are annotated as @Field("categories_*")
         // if the field was annotated as a dynamic field, convert the name 
into a pattern
-        // the wildcard (*) is supposed to be either a prefix or a suffix, 
hence the use of
-        // replaceFirst
-        name = annotation.value().replaceFirst("\\*", "\\.*");
-        dynamicFieldNamePatternMatcher = Pattern.compile("^" + name + "$");
+        // the wildcard (*) is supposed to be either a prefix or a suffix
+
+        if (annotation.value().startsWith("*")) {
+          // handle suffix
+          name = annotation.value();
+          String pattern = annotation.value().substring(1);
+          dynamicFieldNamePatternMatcher = fieldName -> 
fieldName.endsWith(pattern);
+        } else if (annotation.value().endsWith("*")) {
+          // handle prefix
+          name = annotation.value();
+          String pattern = annotation.value().substring(0, 
annotation.value().length() - 1);
+          dynamicFieldNamePatternMatcher = fieldName -> 
fieldName.startsWith(pattern);
+        } else {
+          // handle when wildcard is in the middle
+          name = annotation.value().replaceFirst("\\*", "\\.*");
+          Pattern compiledPattern = Pattern.compile("^" + name + "$");
+          dynamicFieldNamePatternMatcher = fieldName -> 
compiledPattern.matcher(fieldName).find();
+        }
       } else {
         name = annotation.value();
       }
@@ -398,7 +412,7 @@ public class DocumentObjectBinder {
       }
 
       for (String field : solrDocument.getFieldNames()) {
-        if (dynamicFieldNamePatternMatcher.matcher(field).find()) {
+        if (dynamicFieldNamePatternMatcher.test(field)) {
           Object val = solrDocument.getFieldValue(field);
           if (val == null) {
             continue;
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/beans/TestDocumentObjectBinder.java
 
b/solr/solrj/src/test/org/apache/solr/client/solrj/beans/TestDocumentObjectBinder.java
index 8d65a55ade1..2740ead1d93 100644
--- 
a/solr/solrj/src/test/org/apache/solr/client/solrj/beans/TestDocumentObjectBinder.java
+++ 
b/solr/solrj/src/test/org/apache/solr/client/solrj/beans/TestDocumentObjectBinder.java
@@ -98,6 +98,12 @@ public class TestDocumentObjectBinder extends SolrTestCase {
 
     List<String> supplierTwo = l.get(3).supplier.get("supplier_2");
     assertEquals("CCTV Store", supplierTwo.get(0));
+
+    String supplierMiddle = 
l.get(3).supplier_middle.get("supmiddle_mobile_middle");
+    assertEquals("Mobile Store in Middle", supplierMiddle);
+
+    String supplierBeginning = 
l.get(3).sup_beginning.get("mobile_supbeginning");
+    assertEquals("Mobile Store with Beginning Wildcard", supplierBeginning);
   }
 
   public void testChild() throws Exception {
@@ -182,6 +188,12 @@ public class TestDocumentObjectBinder extends SolrTestCase 
{
     @Field("sup_simple_*")
     Map<String, String> supplier_simple;
 
+    @Field("supmiddle_*_middle")
+    Map<String, String> supplier_middle;
+
+    @Field("*_supbeginning")
+    Map<String, String> sup_beginning;
+
     private String[] allSuppliers;
 
     @Field("supplier_*")
@@ -193,6 +205,22 @@ public class TestDocumentObjectBinder extends SolrTestCase 
{
       return this.allSuppliers;
     }
 
+    public Map<String, String> getSupplier_middle() {
+      return supplier_middle;
+    }
+
+    public void setSupplier_middle(Map<String, String> supplier_middle) {
+      this.supplier_middle = supplier_middle;
+    }
+
+    public Map<String, String> getSup_beginning() {
+      return sup_beginning;
+    }
+
+    public void setSup_beginning(Map<String, String> sup_beginning) {
+      this.sup_beginning = sup_beginning;
+    }
+
     @Field
     public void setInStock(Boolean b) {
       inStock = b;
@@ -275,6 +303,7 @@ public class TestDocumentObjectBinder extends SolrTestCase {
           + "<str name=\"manu\">Belkin</str><str name=\"name\">iPod &amp; iPod 
Mini USB 2.0 Cable</str>"
           + "<int name=\"popularity\">1</int><float 
name=\"price\">11.5</float><str name=\"sku\">IW-02</str>"
           + "<str name=\"supplier_1\">Mobile Store</str><str 
name=\"supplier_1\">iPod Store</str><str name=\"supplier_2\">CCTV Store</str>"
+          + "<str name=\"supmiddle_mobile_middle\">Mobile Store in 
Middle</str><str name=\"mobile_supbeginning\">Mobile Store with Beginning 
Wildcard</str>"
           + "<date name=\"timestamp\">2008-04-16T10:35:57.140Z</date><float 
name=\"weight\">2.0</float></doc></result>\n"
           + "</response>";
 }

Reply via email to