Skip to content

Commit

Permalink
Added sort option for deleteOne and updateOne command (#399)
Browse files Browse the repository at this point in the history
  • Loading branch information
maheshrajamani authored Apr 26, 2023
1 parent 75400c2 commit b85bb4a
Show file tree
Hide file tree
Showing 11 changed files with 381 additions and 59 deletions.
4 changes: 3 additions & 1 deletion src/main/java/io/stargate/sgv2/jsonapi/StargateJsonApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@
"$set": {"location": "New York"},
"$push": {"tags": "marathon"}
},
"sort" : {"race.start_date" : 1},
"options" : {
"upsert" : true
}
Expand Down Expand Up @@ -203,7 +204,8 @@
"""
{
"deleteOne": {
"filter": {"_id": "1"}
"filter": {"_id": "1"},
"sort" : {"race.start_date" : 1}
}
}
"""),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import io.stargate.sgv2.jsonapi.api.model.command.ModifyCommand;
import io.stargate.sgv2.jsonapi.api.model.command.NoOptionsCommand;
import io.stargate.sgv2.jsonapi.api.model.command.clause.filter.FilterClause;
import io.stargate.sgv2.jsonapi.api.model.command.clause.sort.SortClause;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
Expand All @@ -25,5 +26,6 @@ public record DeleteOneCommand(
implementation = FilterClause.class)
@Valid
@JsonProperty("filter")
FilterClause filterClause)
FilterClause filterClause,
@Valid @JsonProperty("sort") SortClause sortClause)
implements ModifyCommand, NoOptionsCommand, Filterable {}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import io.stargate.sgv2.jsonapi.api.model.command.Filterable;
import io.stargate.sgv2.jsonapi.api.model.command.ReadCommand;
import io.stargate.sgv2.jsonapi.api.model.command.clause.filter.FilterClause;
import io.stargate.sgv2.jsonapi.api.model.command.clause.sort.SortClause;
import io.stargate.sgv2.jsonapi.api.model.command.clause.update.UpdateClause;
import javax.annotation.Nullable;
import javax.validation.Valid;
Expand All @@ -18,6 +19,7 @@
public record UpdateOneCommand(
@Valid @JsonProperty("filter") FilterClause filterClause,
@NotNull @Valid @JsonProperty("update") UpdateClause updateClause,
@Valid @JsonProperty("sort") SortClause sortClause,
@Nullable Options options)
implements ReadCommand, Filterable {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import io.stargate.sgv2.jsonapi.api.model.command.CommandContext;
import io.stargate.sgv2.jsonapi.api.model.command.clause.sort.SortClause;
import io.stargate.sgv2.jsonapi.api.model.command.impl.DeleteOneCommand;
import io.stargate.sgv2.jsonapi.config.OperationsConfig;
import io.stargate.sgv2.jsonapi.service.operation.model.Operation;
Expand All @@ -12,6 +13,7 @@
import io.stargate.sgv2.jsonapi.service.projection.DocumentProjector;
import io.stargate.sgv2.jsonapi.service.resolver.model.CommandResolver;
import io.stargate.sgv2.jsonapi.service.resolver.model.impl.matcher.FilterableResolver;
import io.stargate.sgv2.jsonapi.util.SortClauseUtil;
import java.util.List;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
Expand Down Expand Up @@ -47,17 +49,35 @@ public Class<DeleteOneCommand> getCommandClass() {

private FindOperation getFindOperation(CommandContext commandContext, DeleteOneCommand command) {
List<DBFilterBase> filters = resolve(commandContext, command);
return new FindOperation(
commandContext,
filters,
DocumentProjector.identityProjector(),
null,
1,
1,
ReadType.KEY,
objectMapper,
null,
0,
0);
final SortClause sortClause = command.sortClause();
List<FindOperation.OrderBy> orderBy = SortClauseUtil.resolveOrderBy(sortClause);
// If orderBy present
if (orderBy != null) {
return FindOperation.sorted(
commandContext,
filters,
DocumentProjector.identityProjector(),
null,
1,
// For in memory sorting we read more data than needed, so defaultSortPageSize like 100
operationsConfig.defaultSortPageSize(),
ReadType.SORTED_DOCUMENT,
objectMapper,
orderBy,
0,
// For in memory sorting if no limit provided in the request will use
// documentConfig.defaultPageSize() as limit
operationsConfig.maxDocumentSortCount());
} else {
return FindOperation.unsorted(
commandContext,
filters,
DocumentProjector.identityProjector(),
null,
1,
1,
ReadType.KEY,
objectMapper);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import io.stargate.sgv2.jsonapi.api.model.command.CommandContext;
import io.stargate.sgv2.jsonapi.api.model.command.clause.sort.SortClause;
import io.stargate.sgv2.jsonapi.api.model.command.impl.UpdateOneCommand;
import io.stargate.sgv2.jsonapi.config.OperationsConfig;
import io.stargate.sgv2.jsonapi.service.operation.model.Operation;
Expand All @@ -14,6 +15,7 @@
import io.stargate.sgv2.jsonapi.service.resolver.model.impl.matcher.FilterableResolver;
import io.stargate.sgv2.jsonapi.service.shredding.Shredder;
import io.stargate.sgv2.jsonapi.service.updater.DocumentUpdater;
import io.stargate.sgv2.jsonapi.util.SortClauseUtil;
import java.util.List;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
Expand Down Expand Up @@ -66,17 +68,35 @@ public Operation resolveCommand(CommandContext commandContext, UpdateOneCommand

private FindOperation getFindOperation(CommandContext commandContext, UpdateOneCommand command) {
List<DBFilterBase> filters = resolve(commandContext, command);
return new FindOperation(
commandContext,
filters,
DocumentProjector.identityProjector(),
null,
1,
1,
ReadType.DOCUMENT,
objectMapper,
null,
0,
0);
final SortClause sortClause = command.sortClause();
List<FindOperation.OrderBy> orderBy = SortClauseUtil.resolveOrderBy(sortClause);
// If orderBy present
if (orderBy != null) {
return FindOperation.sorted(
commandContext,
filters,
DocumentProjector.identityProjector(),
null,
1,
// For in memory sorting we read more data than needed, so defaultSortPageSize like 100
operationsConfig.defaultSortPageSize(),
ReadType.SORTED_DOCUMENT,
objectMapper,
orderBy,
0,
// For in memory sorting if no limit provided in the request will use
// documentConfig.defaultPageSize() as limit
operationsConfig.maxDocumentSortCount());
} else {
return FindOperation.unsorted(
commandContext,
filters,
DocumentProjector.identityProjector(),
null,
1,
1,
ReadType.DOCUMENT,
objectMapper);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import io.stargate.sgv2.jsonapi.api.model.command.impl.FindOneCommand;
import io.stargate.sgv2.jsonapi.api.model.command.impl.InsertManyCommand;
import io.stargate.sgv2.jsonapi.api.model.command.impl.InsertOneCommand;
import io.stargate.sgv2.jsonapi.api.model.command.impl.UpdateOneCommand;
import java.util.List;
import javax.inject.Inject;
import org.assertj.core.api.Assertions;
Expand Down Expand Up @@ -176,38 +175,6 @@ public void happyPath() throws Exception {
}
}

@Nested
class UpdateOne {
@Test
public void happyPath() throws Exception {
String json =
"""
{
"updateOne": {
"filter" : {"username" : "update_user5"},
"update" : {"$set" : {"new_col": {"sub_doc_col" : "new_val2"}}},
"options" : {}
}
}
""";

Command result = objectMapper.readValue(json, Command.class);

assertThat(result)
.isInstanceOfSatisfying(
UpdateOneCommand.class,
updateOneCommand -> {
FilterClause filterClause = updateOneCommand.filterClause();
assertThat(filterClause).isNotNull();
final UpdateClause updateClause = updateOneCommand.updateClause();
assertThat(updateClause).isNotNull();
assertThat(updateClause.buildOperations()).hasSize(1);
final UpdateOneCommand.Options options = updateOneCommand.options();
assertThat(options).isNotNull();
});
}
}

@Nested
class FindOneAndUpdate {
@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.TestProfile;
import io.stargate.sgv2.common.testprofiles.NoGlobalResourcesTestProfile;
import io.stargate.sgv2.jsonapi.api.model.command.Command;
import io.stargate.sgv2.jsonapi.api.model.command.clause.filter.FilterClause;
import io.stargate.sgv2.jsonapi.api.model.command.clause.sort.SortClause;
import io.stargate.sgv2.jsonapi.api.model.command.clause.update.UpdateClause;
import java.util.Set;
import javax.inject.Inject;
import javax.validation.ConstraintViolation;
Expand All @@ -23,6 +27,40 @@ class UpdateOneCommandTest {

@Nested
class Validation {
@Test
public void happyPath() throws Exception {
String json =
"""
{
"updateOne": {
"filter" : {"username" : "update_user5"},
"update" : {"$set" : {"new_col": {"sub_doc_col" : "new_val2"}}},
"sort" : {"username" : 1},
"options" : {}
}
}
""";

Command result = objectMapper.readValue(json, Command.class);

assertThat(result)
.isInstanceOfSatisfying(
UpdateOneCommand.class,
updateOneCommand -> {
FilterClause filterClause = updateOneCommand.filterClause();
assertThat(filterClause).isNotNull();
final UpdateClause updateClause = updateOneCommand.updateClause();
assertThat(updateClause).isNotNull();
assertThat(updateClause.buildOperations()).hasSize(1);
final SortClause sortClause = updateOneCommand.sortClause();
assertThat(sortClause).isNotNull();
assertThat(sortClause.sortExpressions()).hasSize(1);
assertThat(sortClause.sortExpressions().get(0).path()).isEqualTo("username");
assertThat(sortClause.sortExpressions().get(0).ascending()).isTrue();
final UpdateOneCommand.Options options = updateOneCommand.options();
assertThat(options).isNotNull();
});
}

@Test
public void noUpdateClause() throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;

Expand Down Expand Up @@ -322,6 +323,71 @@ public void noMatch() {
.body("status", is(nullValue()))
.body("errors", is(nullValue()));
}

@Test
public void withSort() {
String document =
"""
{
"_id": "doc7",
"username": "user7",
"active_user" : true
}
""";
insertDoc(document);

String document1 =
"""
{
"_id": "doc6",
"username": "user6",
"active_user" : true
}
""";
insertDoc(document1);

String json =
"""
{
"deleteOne": {
"filter" : {"active_user" : true},
"sort" : {"username" : 1}
}
}
""";
given()
.header(HttpConstants.AUTHENTICATION_TOKEN_HEADER_NAME, getAuthToken())
.contentType(ContentType.JSON)
.body(json)
.when()
.post(CollectionResource.BASE_PATH, namespaceName, collectionName)
.then()
.statusCode(200)
.body("status.deletedCount", is(1))
.body("errors", is(nullValue()));

// assert state after update
json =
"""
{
"find": {
"filter" : {"_id" : "doc6"}
}
}
""";
given()
.header(HttpConstants.AUTHENTICATION_TOKEN_HEADER_NAME, getAuthToken())
.contentType(ContentType.JSON)
.body(json)
.when()
.post(CollectionResource.BASE_PATH, namespaceName, collectionName)
.then()
.statusCode(200)
.body("data.docs", hasSize(0));

// cleanUp
deleteAllDocuments();
}
}

@Nested
Expand Down
Loading

0 comments on commit b85bb4a

Please sign in to comment.