7777import org .apache .calcite .util .NlsString ;
7878import org .apache .calcite .util .RangeSets ;
7979import org .apache .calcite .util .Sarg ;
80+ import org .apache .lucene .search .join .ScoreMode ;
8081import org .opensearch .index .mapper .DateFieldMapper ;
8182import org .opensearch .index .query .BoolQueryBuilder ;
8283import org .opensearch .index .query .QueryBuilder ;
84+ import org .opensearch .index .query .QueryBuilders ;
8385import org .opensearch .index .query .RangeQueryBuilder ;
8486import org .opensearch .index .query .ScriptQueryBuilder ;
8587import org .opensearch .script .Script ;
8688import org .opensearch .sql .calcite .plan .OpenSearchConstants ;
8789import org .opensearch .sql .calcite .type .ExprIPType ;
8890import org .opensearch .sql .calcite .type .ExprSqlType ;
8991import org .opensearch .sql .calcite .utils .OpenSearchTypeFactory .ExprUDT ;
92+ import org .opensearch .sql .calcite .utils .PlanUtils ;
9093import org .opensearch .sql .calcite .utils .UserDefinedFunctionUtils ;
9194import org .opensearch .sql .data .model .ExprIpValue ;
9295import org .opensearch .sql .data .model .ExprTimestampValue ;
@@ -1450,6 +1453,8 @@ public static class ScriptQueryExpression extends QueryExpression {
14501453 private final Supplier <String > codeGenerator ;
14511454 private String generatedCode ;
14521455 private final ScriptParameterHelper parameterHelper ;
1456+ private final Map <String , ExprType > fieldTypes ;
1457+ private final List <String > referredFields ;
14531458
14541459 public ScriptQueryExpression (
14551460 RexNode rexNode ,
@@ -1471,6 +1476,12 @@ public ScriptQueryExpression(
14711476 () ->
14721477 SerializationWrapper .wrapWithLangType (
14731478 ScriptEngineType .CALCITE , serializer .serialize (rexNode , parameterHelper ));
1479+ this .referredFields =
1480+ PlanUtils .getInputRefs (rexNode ).stream ()
1481+ .map (RexInputRef ::getIndex )
1482+ .map (rowType .getFieldNames ()::get )
1483+ .toList ();
1484+ this .fieldTypes = fieldTypes ;
14741485 }
14751486
14761487 // For filter script, this method will be called after planning phase;
@@ -1485,7 +1496,12 @@ private String getOrCreateGeneratedCode() {
14851496
14861497 @ Override
14871498 public QueryBuilder builder () {
1488- return new ScriptQueryBuilder (getScript ());
1499+ ScriptQueryBuilder scriptQuery = QueryBuilders .scriptQuery (getScript ());
1500+ String nestedPath = findNestedPath (fieldTypes );
1501+ if (nestedPath != null ) {
1502+ return QueryBuilders .nestedQuery (nestedPath , scriptQuery , ScoreMode .None );
1503+ }
1504+ return scriptQuery ;
14891505 }
14901506
14911507 public Script getScript () {
@@ -1511,6 +1527,45 @@ public void updateAnalyzedNodes(RexNode rexNode) {
15111527 public List <RexNode > getUnAnalyzableNodes () {
15121528 return List .of ();
15131529 }
1530+
1531+ /**
1532+ * Find the nested path for fields referenced in the expression. If multiple nested paths exist,
1533+ * returns the top one.
1534+ *
1535+ * @param fieldTypes Map of field names to their types
1536+ * @return The nested path, or null if no nested fields are found
1537+ */
1538+ private String findNestedPath (Map <String , ExprType > fieldTypes ) {
1539+ if (fieldTypes == null || fieldTypes .isEmpty ()) {
1540+ return null ;
1541+ }
1542+
1543+ for (String fieldName : referredFields ) {
1544+ // Check if the field is part of a nested structure
1545+ // For a field like "items.name", we need to check if "items" is nested
1546+ if (fieldName .contains ("." )) {
1547+ String [] parts = fieldName .split ("\\ ." );
1548+ StringBuilder pathBuilder = new StringBuilder ();
1549+
1550+ // Build up the path progressively and check if any parent is nested
1551+ for (int i = 0 ; i < parts .length - 1 ; i ++) {
1552+ if (i > 0 ) {
1553+ pathBuilder .append ("." );
1554+ }
1555+ pathBuilder .append (parts [i ]);
1556+ String currentPath = pathBuilder .toString ();
1557+
1558+ // Check if this path exists in fieldTypes and is nested
1559+ ExprType pathType = fieldTypes .get (currentPath );
1560+ // OpenSearchDataType.Nested is mapped to ExprCoreType.ARRAY
1561+ if (pathType == ExprCoreType .ARRAY ) {
1562+ return currentPath ;
1563+ }
1564+ }
1565+ }
1566+ }
1567+ return null ;
1568+ }
15141569 }
15151570
15161571 /**
0 commit comments