diff --git a/core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java b/core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java
index 68a700b66b5..53e7edcaa80 100644
--- a/core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java
+++ b/core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java
@@ -452,7 +452,16 @@ private List<RexNode> expandProjectFields(
             }
             matchingFields.forEach(f -> expandedFields.add(context.relBuilder.field(f)));
           } else if (addedFields.add(fieldName)) {
-            expandedFields.add(rexVisitor.analyze(field, context));
+            RexNode resolved = rexVisitor.analyze(field, context);
+            /*
+             * Dotted path access is resolved into ITEM(map, path) function call without aliasing.
+             * Re-apply the alias so the projected column retains the user-visible name.
+             * TODO: Introduce path navigation semantics without relying on projection-time aliasing.
+             */
+            if (resolved.getKind() == SqlKind.ITEM) {
+              resolved = context.relBuilder.alias(resolved, fieldName);
+            }
+            expandedFields.add(resolved);
           }
         }
         case AllFields ignored -> {
diff --git a/core/src/main/java/org/opensearch/sql/calcite/QualifiedNameResolver.java b/core/src/main/java/org/opensearch/sql/calcite/QualifiedNameResolver.java
index a6fcfda4635..917e907a806 100644
--- a/core/src/main/java/org/opensearch/sql/calcite/QualifiedNameResolver.java
+++ b/core/src/main/java/org/opensearch/sql/calcite/QualifiedNameResolver.java
@@ -95,7 +95,7 @@ private static RexNode resolveInNonJoinCondition(
   private static String joinParts(List<String> parts, int start, int length) {
     StringBuilder sb = new StringBuilder();
     for (int i = 0; i < length; i++) {
-      if (start < i) {
+      if (i > 0) {
         sb.append(".");
       }
       sb.append(parts.get(start + i));
@@ -289,9 +289,7 @@ private static RexNode resolveFieldAccess(
       return field;
     } else {
       String itemName = joinParts(parts, length + start, parts.size() - length);
-      return context.relBuilder.alias(
-          createItemAccess(field, itemName, context),
-          String.join(QualifiedName.DELIMITER, parts.subList(start, parts.size())));
+      return createItemAccess(field, itemName, context);
     }
   }
 
diff --git a/docs/user/ppl/cmd/spath.md b/docs/user/ppl/cmd/spath.md
index d62d14fea65..62cb2399915 100644
--- a/docs/user/ppl/cmd/spath.md
+++ b/docs/user/ppl/cmd/spath.md
@@ -143,25 +143,25 @@ fetched rows / total rows = 3/3
 
 ## Example 5: Auto-extract mode  
 
-When `path` is omitted, `spath` extracts all fields from the JSON into a map. All values are stringified, and null values are preserved:
+When `path` is omitted, `spath` extracts all fields from the JSON into a map. You can access individual values using dotted path navigation, where `doc.user.name` resolves to the map key `user.name`. For keys containing special characters like `{}`, use backtick quoting:
   
 ```ppl
 source=structured
-| spath input=doc_auto output=result
-| fields doc_auto result
+| spath input=doc_auto output=doc
+| fields doc_auto, doc.user.name, doc.user.age, doc.`tags{}`, doc.active
 ```
   
 The query returns the following results:
   
 ```text
 fetched rows / total rows = 3/3
-+---------------------------------------------------------------------------------+------------------------------------------------------------------------------------+
-| doc_auto                                                                        | result                                                                             |
-|---------------------------------------------------------------------------------+------------------------------------------------------------------------------------|
-| {"user":{"name":"John","age":30},"tags":["java","sql"],"active":true}           | {'user.age': '30', 'tags{}': '[java, sql]', 'user.name': 'John', 'active': 'true'} |
-| {"user":{"name":"Jane","age":25},"tags":["python"],"active":null}               | {'user.age': '25', 'tags{}': 'python', 'user.name': 'Jane', 'active': 'null'}      |
-| {"user":{"name":"Bob","age":35},"tags":["go","rust","sql"],"user.name":"Bobby"} | {'user.age': '35', 'tags{}': '[go, rust, sql]', 'user.name': '[Bob, Bobby]'}       |
-+---------------------------------------------------------------------------------+------------------------------------------------------------------------------------+
++---------------------------------------------------------------------------------+---------------+--------------+-----------------+------------+
+| doc_auto                                                                        | doc.user.name | doc.user.age | doc.tags{}      | doc.active |
+|---------------------------------------------------------------------------------+---------------+--------------+-----------------+------------|
+| {"user":{"name":"John","age":30},"tags":["java","sql"],"active":true}           | John          | 30           | [java, sql]     | true       |
+| {"user":{"name":"Jane","age":25},"tags":["python"],"active":null}               | Jane          | 25           | python          | null       |
+| {"user":{"name":"Bob","age":35},"tags":["go","rust","sql"],"user.name":"Bobby"} | [Bob, Bobby]  | 35           | [go, rust, sql] | null       |
++---------------------------------------------------------------------------------+---------------+--------------+-----------------+------------+
 ```
   
 The flattening rules demonstrated in this example:
@@ -171,4 +171,3 @@ The flattening rules demonstrated in this example:
 - Duplicate logical keys merge into arrays: in the third row, both `"user": {"name": "Bob"}` (nested) and `"user.name": "Bobby"` (direct dotted key) resolve to the same key `user.name`, so their values merge into `'[Bob, Bobby]'`
 - All values are strings: numeric `30` becomes `'30'`, boolean `true` becomes `'true'`, and arrays become strings like `'[java, sql]'`
 - Null values are preserved: in the second row, `"active": null` is kept as `'active': 'null'` in the map
-  
diff --git a/integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalcitePPLSpathCommandIT.java b/integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalcitePPLSpathCommandIT.java
index f3247e968ba..ec6f8583b23 100644
--- a/integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalcitePPLSpathCommandIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalcitePPLSpathCommandIT.java
@@ -8,6 +8,7 @@
 import static org.opensearch.sql.util.MatcherUtils.rows;
 import static org.opensearch.sql.util.MatcherUtils.schema;
 import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
+import static org.opensearch.sql.util.MatcherUtils.verifyDataRowsInOrder;
 import static org.opensearch.sql.util.MatcherUtils.verifySchema;
 
 import java.io.IOException;
@@ -48,6 +49,17 @@ public void init() throws Exception {
             + " \"malformed_doc\": \"{\\\"user\\\":{\\\"name\\\":\"}");
     client().performRequest(autoExtractDoc);
 
+    // Auto-extract mode: 2-doc index for spath + command (eval/where/stats/sort) tests
+    Request cmdDoc1 = new Request("PUT", "/test_spath_cmd/_doc/1?refresh=true");
+    cmdDoc1.setJsonEntity(
+        "{\"doc\": \"{\\\"user\\\":{\\\"name\\\":\\\"John\\\",\\\"age\\\":30}}\"}");
+    client().performRequest(cmdDoc1);
+
+    Request cmdDoc2 = new Request("PUT", "/test_spath_cmd/_doc/2?refresh=true");
+    cmdDoc2.setJsonEntity(
+        "{\"doc\": \"{\\\"user\\\":{\\\"name\\\":\\\"Alice\\\",\\\"age\\\":25}}\"}");
+    client().performRequest(cmdDoc2);
+
     // Auto-extract mode: null input handling (doc 1 establishes mapping, doc 2 has null)
     Request nullDoc1 = new Request("PUT", "/test_spath_null/_doc/1?refresh=true");
     nullDoc1.setJsonEntity("{\"doc\": \"{\\\"n\\\": 1}\"}");
@@ -163,4 +175,45 @@ public void testSpathAutoExtractMalformedJson() throws IOException {
     verifySchema(result, schema("result", "struct"));
     verifyDataRows(result, rows(new JSONObject("{}")));
   }
+
+  @Test
+  public void testSpathAutoExtractWithEval() throws IOException {
+    JSONObject result =
+        executeQuery(
+            "source=test_spath_cmd | spath input=doc"
+                + " | eval name = doc.user.name | fields name");
+    verifySchema(result, schema("name", "string"));
+    verifyDataRows(result, rows("Alice"), rows("John"));
+  }
+
+  @Test
+  public void testSpathAutoExtractWithWhere() throws IOException {
+    JSONObject result =
+        executeQuery(
+            "source=test_spath_cmd | spath input=doc"
+                + " | where doc.user.name = 'John' | fields doc.user.name");
+    verifySchema(result, schema("doc.user.name", "string"));
+    verifyDataRows(result, rows("John"));
+  }
+
+  @Test
+  public void testSpathAutoExtractWithStats() throws IOException {
+    JSONObject result =
+        executeQuery(
+            "source=test_spath_cmd | spath input=doc"
+                + " | stats sum(doc.user.age) by doc.user.name");
+    verifySchema(result, schema("sum(doc.user.age)", "double"), schema("doc.user.name", "string"));
+    verifyDataRows(result, rows(25, "Alice"), rows(30, "John"));
+  }
+
+  @Test
+  public void testSpathAutoExtractWithSort() throws IOException {
+    // spath auto-extract + sort by path navigation on result
+    JSONObject result =
+        executeQuery(
+            "source=test_spath_cmd | spath input=doc"
+                + " | sort doc.user.name | fields doc.user.name");
+    verifySchema(result, schema("doc.user.name", "string"));
+    verifyDataRowsInOrder(result, rows("Alice"), rows("John"));
+  }
 }
diff --git a/ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLSpathTest.java b/ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLSpathTest.java
index 8970d593dcf..9967b10543e 100644
--- a/ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLSpathTest.java
+++ b/ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLSpathTest.java
@@ -58,4 +58,90 @@ public void testSpathAutoExtractModeWithOutput() {
                 + "  LogicalTableScan(table=[[scott, EMP]])\n")
         .expectSparkSQL("SELECT JSON_EXTRACT_ALL(`ENAME`) `result`\n" + "FROM `scott`.`EMP`");
   }
+
+  @Test
+  public void testSpathAutoExtractModeWithEval() {
+    withPPLQuery(
+            "source=EMP | spath input=ENAME output=result"
+                + " | eval age = result.user.age + 1 | fields age")
+        .expectLogical(
+            "LogicalProject(age=[+(SAFE_CAST(ITEM(JSON_EXTRACT_ALL($1),"
+                + " 'user.age')), 1.0E0)])\n"
+                + "  LogicalTableScan(table=[[scott, EMP]])\n")
+        .expectSparkSQL(
+            "SELECT TRY_CAST(JSON_EXTRACT_ALL(`ENAME`)['user.age']"
+                + " AS DOUBLE) + 1.0E0 `age`\n"
+                + "FROM `scott`.`EMP`");
+  }
+
+  @Test
+  public void testSpathAutoExtractModeWithStats() {
+    withPPLQuery("source=EMP | spath input=ENAME output=result | stats count() by result.user.name")
+        .expectLogical(
+            "LogicalProject(count()=[$1], result.user.name=[$0])\n"
+                + "  LogicalAggregate(group=[{0}], count()=[COUNT()])\n"
+                + "    LogicalProject(result.user.name=[ITEM(JSON_EXTRACT_ALL($1),"
+                + " 'user.name')])\n"
+                + "      LogicalTableScan(table=[[scott, EMP]])\n")
+        .expectSparkSQL(
+            "SELECT COUNT(*) `count()`,"
+                + " JSON_EXTRACT_ALL(`ENAME`)['user.name'] `result.user.name`\n"
+                + "FROM `scott`.`EMP`\n"
+                + "GROUP BY JSON_EXTRACT_ALL(`ENAME`)['user.name']");
+  }
+
+  @Test
+  public void testSpathAutoExtractModeWithWhere() {
+    withPPLQuery("source=EMP | spath input=ENAME output=result" + " | where result.active = 'true'")
+        .expectLogical(
+            "LogicalFilter(condition=[=(ITEM($8, 'active'),"
+                + " 'true')])\n"
+                + "  LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3],"
+                + " HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7],"
+                + " result=[JSON_EXTRACT_ALL($1)])\n"
+                + "    LogicalTableScan(table=[[scott, EMP]])\n")
+        .expectSparkSQL(
+            "SELECT *\n"
+                + "FROM (SELECT `EMPNO`, `ENAME`, `JOB`, `MGR`, `HIREDATE`,"
+                + " `SAL`, `COMM`, `DEPTNO`, JSON_EXTRACT_ALL(`ENAME`) `result`\n"
+                + "FROM `scott`.`EMP`) `t`\n"
+                + "WHERE `result`['active'] = 'true'");
+  }
+
+  @Test
+  public void testSpathAutoExtractModeWithFields() {
+    withPPLQuery(
+            "source=EMP | spath input=ENAME output=result"
+                + " | fields result.user.name, result.user.age")
+        .expectLogical(
+            "LogicalProject(result.user.name=[ITEM(JSON_EXTRACT_ALL($1), 'user.name')],"
+                + " result.user.age=[ITEM(JSON_EXTRACT_ALL($1), 'user.age')])\n"
+                + "  LogicalTableScan(table=[[scott, EMP]])\n")
+        .expectSparkSQL(
+            "SELECT JSON_EXTRACT_ALL(`ENAME`)['user.name'] `result.user.name`,"
+                + " JSON_EXTRACT_ALL(`ENAME`)['user.age'] `result.user.age`\n"
+                + "FROM `scott`.`EMP`");
+  }
+
+  @Test
+  public void testSpathAutoExtractModeWithSort() {
+    withPPLQuery("source=EMP | spath input=ENAME output=result" + " | sort result.user.name")
+        .expectLogical(
+            "LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3],"
+                + " HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], result=[$8])\n"
+                + "  LogicalSort(sort0=[$9], dir0=[ASC-nulls-first])\n"
+                + "    LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3],"
+                + " HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7],"
+                + " result=[JSON_EXTRACT_ALL($1)],"
+                + " $f9=[ITEM(JSON_EXTRACT_ALL($1), 'user.name')])\n"
+                + "      LogicalTableScan(table=[[scott, EMP]])\n")
+        .expectSparkSQL(
+            "SELECT `EMPNO`, `ENAME`, `JOB`, `MGR`, `HIREDATE`,"
+                + " `SAL`, `COMM`, `DEPTNO`, `result`\n"
+                + "FROM (SELECT `EMPNO`, `ENAME`, `JOB`, `MGR`, `HIREDATE`,"
+                + " `SAL`, `COMM`, `DEPTNO`, JSON_EXTRACT_ALL(`ENAME`) `result`,"
+                + " JSON_EXTRACT_ALL(`ENAME`)['user.name'] `$f9`\n"
+                + "FROM `scott`.`EMP`\n"
+                + "ORDER BY 10) `t0`");
+  }
 }
