Skip to content

Commit 111e083

Browse files
ENGTAI-68310 : Adding logic and fixing order (#232)
* Adding logic and fixing order * Added test * postgres fix --------- Co-authored-by: Suresh Prakash <[email protected]>
1 parent 4adcb5e commit 111e083

File tree

6 files changed

+150
-2
lines changed

6 files changed

+150
-2
lines changed

document-store/src/integrationTest/java/org/hypertrace/core/documentstore/ArrayFiltersQueryIntegrationTest.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,54 @@ void getSolarSystemsWithNoneOfThePlanetsHavingBothWaterAndOxygenTogether(
296296
JSONAssert.assertEquals(expected, actual, JSONCompareMode.LENIENT);
297297
}
298298

299+
/**
300+
* Tests returning documents where environment IDs are a subset of the provided allowed
301+
* environment IDs.
302+
*/
303+
@ParameterizedTest
304+
@ArgumentsSource(AllProvider.class)
305+
void getDocumentsWithEnvironmentIdsSubsetOfGivenList(final String dataStoreName)
306+
throws JSONException, IOException {
307+
final String testCollectionName = "environment_scope_test";
308+
final Datastore datastore = datastoreMap.get(dataStoreName);
309+
final Map<Key, Document> testDocuments =
310+
Utils.buildDocumentsFromResource("query/array_operators/environment_scope_test.json");
311+
datastore.deleteCollection(testCollectionName);
312+
datastore.createCollection(testCollectionName, null);
313+
final Collection collection = datastore.getCollection(testCollectionName);
314+
collection.bulkUpsert(testDocuments);
315+
316+
final java.util.List<String> environmentIds = java.util.List.of("env-1", "env-2", "env-3");
317+
318+
final Query query =
319+
Query.builder()
320+
.setFilter(
321+
and(
322+
RelationalExpression.of(
323+
IdentifierExpression.of("scope.environmentScope.environmentIds"),
324+
RelationalOperator.EXISTS,
325+
ConstantExpression.of(true)),
326+
not(
327+
ArrayRelationalFilterExpression.builder()
328+
.operator(ANY)
329+
.filter(
330+
RelationalExpression.of(
331+
IdentifierExpression.of(
332+
"scope.environmentScope.environmentIds"),
333+
RelationalOperator.NOT_IN,
334+
ConstantExpression.ofStrings(environmentIds)))
335+
.build())))
336+
.build();
337+
338+
final Iterator<Document> documents = collection.aggregate(query);
339+
final String expected = readResource("environment_ids_subset.json");
340+
final String actual = iteratorToJson(documents);
341+
342+
datastore.deleteCollection(testCollectionName);
343+
344+
JSONAssert.assertEquals(expected, actual, JSONCompareMode.LENIENT);
345+
}
346+
299347
private String readResource(final String fileName) {
300348
try {
301349
return new String(
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[
2+
{
3+
"scope": {
4+
"environmentScope": {
5+
"environmentIds": ["env-1", "env-2"]
6+
}
7+
},
8+
"name": "Document A"
9+
},
10+
{
11+
"scope": {
12+
"environmentScope": {
13+
"environmentIds": ["env-1", "env-2", "env-3"]
14+
}
15+
},
16+
"name": "Document B"
17+
}
18+
]
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
[
2+
{
3+
"_id": 1,
4+
"name": "Document A",
5+
"scope": {
6+
"environmentScope": {
7+
"environmentIds": ["env-1", "env-2"]
8+
}
9+
}
10+
},
11+
{
12+
"_id": 2,
13+
"name": "Document B",
14+
"scope": {
15+
"environmentScope": {
16+
"environmentIds": ["env-1", "env-2", "env-3"]
17+
}
18+
}
19+
},
20+
{
21+
"_id": 3,
22+
"name": "Document C",
23+
"scope": {
24+
"environmentScope": {
25+
"environmentIds": ["env-1", "env-4"]
26+
}
27+
}
28+
},
29+
{
30+
"_id": 4,
31+
"name": "Document D",
32+
"scope": {
33+
"environmentScope": {
34+
"environmentIds": ["env-5", "env-6"]
35+
}
36+
}
37+
},
38+
{
39+
"_id": 5,
40+
"name": "Document E"
41+
}
42+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.hypertrace.core.documentstore.mongo.query.parser.filter;
2+
3+
import java.util.Map;
4+
import lombok.AllArgsConstructor;
5+
import org.hypertrace.core.documentstore.expression.impl.RelationalExpression;
6+
import org.hypertrace.core.documentstore.mongo.query.parser.filter.MongoRelationalFilterParserFactory.MongoRelationalFilterContext;
7+
8+
/**
9+
* Note: MongoDB does not have a native "NOT IN" aggregation operator. This parser simulates "NOT
10+
* IN" functionality by combining the $not and $in operators.
11+
*/
12+
@AllArgsConstructor
13+
public class MongoNotInExprRelationalFilterParser implements MongoRelationalFilterParser {
14+
private static final String NOT_OP = "$not";
15+
private static final String IN_OP = "$in";
16+
private static final MongoStandardRelationalOperatorMapping mapping =
17+
new MongoStandardRelationalOperatorMapping();
18+
19+
@Override
20+
public Map<String, Object> parse(
21+
final RelationalExpression expression, final MongoRelationalFilterContext context) {
22+
final String parsedLhs = expression.getLhs().accept(context.lhsParser());
23+
final Object parsedRhs = expression.getRhs().accept(context.rhsParser());
24+
return Map.of(NOT_OP, Map.of(IN_OP, new Object[] {parsedLhs, parsedRhs}));
25+
}
26+
}

document-store/src/main/java/org/hypertrace/core/documentstore/mongo/query/parser/filter/MongoRelationalFilterParserFactoryImpl.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,22 @@ public MongoRelationalFilterParser parser(
2626
}
2727

2828
case IN:
29+
if (INSIDE_EXPR.equals(context.location())) {
30+
return new MongoStandardExprRelationalFilterParser();
31+
} else if (OUTSIDE_EXPR.equals(context.location())) {
32+
return new MongoStandardNonExprRelationalFilterParser();
33+
} else {
34+
throw new UnsupportedOperationException("Unsupported location: " + context.location());
35+
}
36+
2937
case NOT_IN:
30-
return new MongoStandardNonExprRelationalFilterParser();
38+
if (INSIDE_EXPR.equals(context.location())) {
39+
return new MongoNotInExprRelationalFilterParser();
40+
} else if (OUTSIDE_EXPR.equals(context.location())) {
41+
return new MongoStandardNonExprRelationalFilterParser();
42+
} else {
43+
throw new UnsupportedOperationException("Unsupported location: " + context.location());
44+
}
3145

3246
case CONTAINS:
3347
return new MongoContainsRelationalFilterParser();

document-store/src/main/java/org/hypertrace/core/documentstore/postgres/query/v1/vistors/PostgresFilterTypeExpressionVisitor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ private String getFilterStringForAnyOperator(final ArrayRelationalFilterExpressi
181181
.accept(new PostgresIdentifierExpressionVisitor(postgresQueryParser));
182182

183183
// If the field name is 'elements.inner', alias becomes 'elements_dot_inner'
184-
final String alias = encodeAliasForNestedField(identifierName);
184+
final String alias = encodeAliasForNestedField(identifierName).toLowerCase();
185185

186186
// Any LHS field name (elements) is to be prefixed with current alias (elements_dot_inner)
187187
final PostgresWrappingFilterVisitorProvider visitorProvider =

0 commit comments

Comments
 (0)