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 & 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>";
}