|
5 | 5 |
|
6 | 6 | package org.opensearch.sql.protocol.response; |
7 | 7 |
|
| 8 | +import static org.opensearch.sql.expression.HighlightExpression.HIGHLIGHT_FIELD; |
| 9 | + |
8 | 10 | import java.util.Collection; |
9 | 11 | import java.util.Iterator; |
10 | 12 | import java.util.LinkedHashMap; |
| 13 | +import java.util.List; |
11 | 14 | import java.util.Locale; |
12 | 15 | import java.util.Map; |
| 16 | +import java.util.stream.Collectors; |
13 | 17 | import lombok.Getter; |
14 | 18 | import org.opensearch.sql.data.model.ExprValue; |
15 | 19 | import org.opensearch.sql.data.model.ExprValueUtils; |
@@ -82,19 +86,46 @@ public Map<String, String> columnNameTypes() { |
82 | 86 |
|
83 | 87 | @Override |
84 | 88 | public Iterator<Object[]> iterator() { |
85 | | - // Any chance to avoid copy for json response generation? |
86 | 89 | return exprValues.stream() |
87 | 90 | .map(ExprValueUtils::getTupleValue) |
88 | | - .map(Map::values) |
89 | | - .map(this::convertExprValuesToValues) |
| 91 | + .map( |
| 92 | + tuple -> |
| 93 | + tuple.entrySet().stream() |
| 94 | + .filter(e -> !HIGHLIGHT_FIELD.equals(e.getKey())) |
| 95 | + .map(e -> e.getValue().value()) |
| 96 | + .toArray(Object[]::new)) |
90 | 97 | .iterator(); |
91 | 98 | } |
92 | 99 |
|
93 | | - private String getColumnName(Column column) { |
94 | | - return (column.getAlias() != null) ? column.getAlias() : column.getName(); |
| 100 | + /** |
| 101 | + * Extract highlight data from each result row. Each row may contain a {@code _highlight} field |
| 102 | + * added by {@code OpenSearchResponse.addHighlightsToBuilder()} and preserved through projection. |
| 103 | + * Returns a list parallel to datarows where each entry is either a map of field name to highlight |
| 104 | + * fragments, or null if no highlight data exists for that row. |
| 105 | + */ |
| 106 | + public List<Map<String, Object>> highlights() { |
| 107 | + return exprValues.stream() |
| 108 | + .map(ExprValueUtils::getTupleValue) |
| 109 | + .map( |
| 110 | + tuple -> { |
| 111 | + ExprValue hl = tuple.get(HIGHLIGHT_FIELD); |
| 112 | + if (hl == null || hl.isMissing() || hl.isNull()) { |
| 113 | + return null; |
| 114 | + } |
| 115 | + Map<String, Object> hlMap = new LinkedHashMap<>(); |
| 116 | + for (Map.Entry<String, ExprValue> entry : hl.tupleValue().entrySet()) { |
| 117 | + hlMap.put( |
| 118 | + entry.getKey(), |
| 119 | + entry.getValue().collectionValue().stream() |
| 120 | + .map(ExprValue::stringValue) |
| 121 | + .collect(Collectors.toList())); |
| 122 | + } |
| 123 | + return (Map<String, Object>) hlMap; |
| 124 | + }) |
| 125 | + .collect(Collectors.toList()); |
95 | 126 | } |
96 | 127 |
|
97 | | - private Object[] convertExprValuesToValues(Collection<ExprValue> exprValues) { |
98 | | - return exprValues.stream().map(ExprValue::value).toArray(Object[]::new); |
| 128 | + private String getColumnName(Column column) { |
| 129 | + return (column.getAlias() != null) ? column.getAlias() : column.getName(); |
99 | 130 | } |
100 | 131 | } |
0 commit comments