Skip to content

Commit 4ed3a3e

Browse files
committed
Add query filter, project, aggregation, sort converters
Signed-off-by: Vinay Krishna Pudyodu <vinkrish.neo@gmail.com>
1 parent 181b4da commit 4ed3a3e

60 files changed

Lines changed: 5665 additions & 45 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.dsl;
10+
11+
import org.opensearch.search.aggregations.AggregationBuilders;
12+
import org.opensearch.search.aggregations.BucketOrder;
13+
import org.opensearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
14+
import org.opensearch.search.builder.SearchSourceBuilder;
15+
16+
/**
17+
* Integration tests for DSL aggregation conversion.
18+
* Uses matchAllQuery; focus is on aggregation plan building.
19+
*/
20+
public class DslAggregationIT extends DslIntegTestBase {
21+
22+
public void testMetricOnly() {
23+
createTestIndex();
24+
assertOk(search(new SearchSourceBuilder().size(0).aggregation(AggregationBuilders.avg("avg_price").field("price"))));
25+
}
26+
27+
public void testMultipleMetrics() {
28+
createTestIndex();
29+
assertOk(
30+
search(
31+
new SearchSourceBuilder().size(0)
32+
.aggregation(AggregationBuilders.avg("avg_price").field("price"))
33+
.aggregation(AggregationBuilders.sum("total_price").field("price"))
34+
.aggregation(AggregationBuilders.min("min_price").field("price"))
35+
.aggregation(AggregationBuilders.max("max_price").field("price"))
36+
)
37+
);
38+
}
39+
40+
public void testTermsBucket() {
41+
createTestIndex();
42+
assertOk(search(new SearchSourceBuilder().size(0).aggregation(new TermsAggregationBuilder("by_brand").field("brand"))));
43+
}
44+
45+
public void testTermsBucketWithMetric() {
46+
createTestIndex();
47+
assertOk(
48+
search(
49+
new SearchSourceBuilder().size(0)
50+
.aggregation(
51+
new TermsAggregationBuilder("by_brand").field("brand")
52+
.subAggregation(AggregationBuilders.avg("avg_price").field("price"))
53+
)
54+
)
55+
);
56+
}
57+
58+
public void testNestedBuckets() {
59+
createTestIndex();
60+
assertOk(
61+
search(
62+
new SearchSourceBuilder().size(0)
63+
.aggregation(
64+
new TermsAggregationBuilder("by_brand").field("brand")
65+
.subAggregation(AggregationBuilders.sum("total").field("price"))
66+
.subAggregation(
67+
new TermsAggregationBuilder("by_name").field("name")
68+
.subAggregation(AggregationBuilders.avg("avg_price").field("price"))
69+
)
70+
)
71+
)
72+
);
73+
}
74+
75+
public void testAggsWithHits() {
76+
createTestIndex();
77+
// size > 0 with aggs produces both HITS + AGGREGATION plans
78+
assertOk(search(new SearchSourceBuilder().size(10).aggregation(AggregationBuilders.avg("avg_price").field("price"))));
79+
}
80+
81+
public void testTermsBucketOrderByKeyAsc() {
82+
createTestIndex();
83+
assertOk(
84+
search(
85+
new SearchSourceBuilder().size(0)
86+
.aggregation(new TermsAggregationBuilder("by_brand").field("brand").order(BucketOrder.key(true)))
87+
)
88+
);
89+
}
90+
91+
public void testTermsBucketOrderByKeyDesc() {
92+
createTestIndex();
93+
assertOk(
94+
search(
95+
new SearchSourceBuilder().size(0)
96+
.aggregation(new TermsAggregationBuilder("by_brand").field("brand").order(BucketOrder.key(false)))
97+
)
98+
);
99+
}
100+
101+
public void testTermsBucketOrderByCountAsc() {
102+
createTestIndex();
103+
assertOk(
104+
search(
105+
new SearchSourceBuilder().size(0)
106+
.aggregation(new TermsAggregationBuilder("by_brand").field("brand").order(BucketOrder.count(true)))
107+
)
108+
);
109+
}
110+
111+
public void testTermsBucketOrderByMetric() {
112+
createTestIndex();
113+
assertOk(
114+
search(
115+
new SearchSourceBuilder().size(0)
116+
.aggregation(
117+
new TermsAggregationBuilder("by_brand").field("brand")
118+
.order(BucketOrder.aggregation("avg_price", false))
119+
.subAggregation(AggregationBuilders.avg("avg_price").field("price"))
120+
)
121+
)
122+
);
123+
}
124+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.dsl;
10+
11+
import org.opensearch.action.search.SearchRequest;
12+
import org.opensearch.action.search.SearchResponse;
13+
import org.opensearch.analytics.AnalyticsPlugin;
14+
import org.opensearch.common.xcontent.XContentType;
15+
import org.opensearch.plugins.Plugin;
16+
import org.opensearch.search.builder.SearchSourceBuilder;
17+
import org.opensearch.test.OpenSearchIntegTestCase;
18+
19+
import java.util.Collection;
20+
import java.util.List;
21+
22+
// TODO: once end-to-end execution returns real results, update ITs to verify
23+
// actual hit count, field values, sort order, and aggregation buckets.
24+
/**
25+
* Base class for DSL query executor integration tests.
26+
* Provides shared index setup and search helper.
27+
*/
28+
@OpenSearchIntegTestCase.ClusterScope(scope = OpenSearchIntegTestCase.Scope.SUITE, numDataNodes = 1)
29+
public abstract class DslIntegTestBase extends OpenSearchIntegTestCase {
30+
31+
protected static final String INDEX = "test-index";
32+
33+
@Override
34+
protected Collection<Class<? extends Plugin>> nodePlugins() {
35+
return List.of(AnalyticsPlugin.class, DslQueryExecutorPlugin.class);
36+
}
37+
38+
protected void createTestIndex() {
39+
createIndex(INDEX);
40+
ensureGreen();
41+
client().prepareIndex(INDEX)
42+
.setId("1")
43+
.setSource("{\"name\":\"laptop\",\"price\":1200,\"brand\":\"brandX\",\"rating\":4.5}", XContentType.JSON)
44+
.get();
45+
refresh(INDEX);
46+
}
47+
48+
protected SearchResponse search(SearchSourceBuilder source) {
49+
return client().search(new SearchRequest(INDEX).source(source)).actionGet();
50+
}
51+
52+
protected void assertOk(SearchResponse response) {
53+
assertNotNull(response);
54+
assertEquals(200, response.status().getStatus());
55+
}
56+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.dsl;
10+
11+
import org.opensearch.search.builder.SearchSourceBuilder;
12+
13+
/**
14+
* Integration tests for DSL _source filtering (projection) conversion.
15+
* Uses matchAllQuery; focus is on _source includes/excludes behavior.
16+
*/
17+
public class DslProjectIT extends DslIntegTestBase {
18+
19+
public void testNoSourceFiltering() {
20+
createTestIndex();
21+
assertOk(search(new SearchSourceBuilder()));
22+
}
23+
24+
public void testIncludeSpecificFields() {
25+
createTestIndex();
26+
assertOk(search(new SearchSourceBuilder().fetchSource(new String[] { "name", "price" }, null)));
27+
}
28+
29+
public void testExcludeFields() {
30+
createTestIndex();
31+
assertOk(search(new SearchSourceBuilder().fetchSource(new String[] {}, new String[] { "rating" })));
32+
}
33+
34+
public void testSourceDisabled() {
35+
createTestIndex();
36+
assertOk(search(new SearchSourceBuilder().fetchSource(false)));
37+
}
38+
39+
public void testWildcardIncludes() {
40+
createTestIndex();
41+
assertOk(search(new SearchSourceBuilder().fetchSource(new String[] { "na*" }, null)));
42+
}
43+
44+
public void testWildcardExcludes() {
45+
createTestIndex();
46+
assertOk(search(new SearchSourceBuilder().fetchSource(new String[] {}, new String[] { "ra*" })));
47+
}
48+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.dsl;
10+
11+
import org.opensearch.action.search.SearchRequest;
12+
import org.opensearch.index.query.QueryBuilders;
13+
import org.opensearch.search.builder.SearchSourceBuilder;
14+
15+
/**
16+
* Integration tests for DSL query conversion (filter path).
17+
* Uses various query types; sort and projection use defaults.
18+
*/
19+
public class DslQueryIT extends DslIntegTestBase {
20+
21+
public void testNoQuery() {
22+
createTestIndex();
23+
assertOk(search(new SearchSourceBuilder()));
24+
}
25+
26+
public void testMatchAll() {
27+
createTestIndex();
28+
assertOk(search(new SearchSourceBuilder().query(QueryBuilders.matchAllQuery())));
29+
}
30+
31+
public void testTermQuery() {
32+
createTestIndex();
33+
assertOk(search(new SearchSourceBuilder().query(QueryBuilders.termQuery("name", "laptop"))));
34+
}
35+
36+
public void testWildcardQueryWithUnresolvedNode() {
37+
createTestIndex();
38+
// Wildcard query is not converted to standard Rex — wraps in UnresolvedQueryCall.
39+
assertOk(search(new SearchSourceBuilder().query(QueryBuilders.wildcardQuery("name", "lap*"))));
40+
}
41+
42+
public void testFailsForNonexistentIndex() {
43+
expectThrows(
44+
Exception.class,
45+
() -> client().search(new SearchRequest("nonexistent-index").source(new SearchSourceBuilder())).actionGet()
46+
);
47+
}
48+
49+
public void testFailsForMultipleIndices() {
50+
createTestIndex();
51+
createIndex("test-index-2");
52+
ensureGreen();
53+
54+
expectThrows(
55+
Exception.class,
56+
() -> client().search(new SearchRequest(INDEX, "test-index-2").source(new SearchSourceBuilder())).actionGet()
57+
);
58+
}
59+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.dsl;
10+
11+
import org.opensearch.search.builder.SearchSourceBuilder;
12+
import org.opensearch.search.sort.SortOrder;
13+
14+
/**
15+
* Integration tests for DSL sort and pagination conversion.
16+
* Uses matchAllQuery; focus is on sort/from/size behavior.
17+
*/
18+
public class DslSortIT extends DslIntegTestBase {
19+
20+
public void testDefaultPagination() {
21+
createTestIndex();
22+
assertOk(search(new SearchSourceBuilder()));
23+
}
24+
25+
public void testSortAscending() {
26+
createTestIndex();
27+
assertOk(search(new SearchSourceBuilder().sort("name", SortOrder.ASC)));
28+
}
29+
30+
public void testSortDescending() {
31+
createTestIndex();
32+
assertOk(search(new SearchSourceBuilder().sort("price", SortOrder.DESC)));
33+
}
34+
35+
public void testMultipleSortFields() {
36+
createTestIndex();
37+
assertOk(search(new SearchSourceBuilder().sort("brand", SortOrder.ASC).sort("price", SortOrder.DESC)));
38+
}
39+
40+
public void testCustomSize() {
41+
createTestIndex();
42+
assertOk(search(new SearchSourceBuilder().size(5)));
43+
}
44+
45+
public void testFromAndSize() {
46+
createTestIndex();
47+
assertOk(search(new SearchSourceBuilder().from(0).size(5)));
48+
}
49+
50+
public void testFromOffset() {
51+
createTestIndex();
52+
assertOk(search(new SearchSourceBuilder().from(10).size(5)));
53+
}
54+
}

0 commit comments

Comments
 (0)