Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Returning Arrays from find and aggregate Operations #251

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ dependencies = [
{org = "ballerina", name = "jballerina.java"},
{org = "ballerina", name = "lang.value"}
]
modules = [
{org = "ballerina", packageName = "io", moduleName = "io"}
]

[[package]]
org = "ballerina"
Expand All @@ -36,6 +39,26 @@ modules = [
{org = "ballerina", packageName = "jballerina.java", moduleName = "jballerina.java"}
]

[[package]]
org = "ballerina"
name = "lang.__internal"
version = "0.0.0"
scope = "testOnly"
dependencies = [
{org = "ballerina", name = "jballerina.java"},
{org = "ballerina", name = "lang.object"}
]

[[package]]
org = "ballerina"
name = "lang.array"
version = "0.0.0"
scope = "testOnly"
dependencies = [
{org = "ballerina", name = "jballerina.java"},
{org = "ballerina", name = "lang.__internal"}
]

[[package]]
org = "ballerina"
name = "lang.error"
Expand All @@ -45,6 +68,12 @@ dependencies = [
{org = "ballerina", name = "jballerina.java"}
]

[[package]]
org = "ballerina"
name = "lang.object"
version = "0.0.0"
scope = "testOnly"

[[package]]
org = "ballerina"
name = "lang.value"
Expand All @@ -70,7 +99,7 @@ modules = [
[[package]]
org = "ballerina"
name = "observe"
version = "1.2.2"
version = "1.2.3"
dependencies = [
{org = "ballerina", name = "jballerina.java"}
]
Expand All @@ -82,6 +111,7 @@ version = "0.0.0"
scope = "testOnly"
dependencies = [
{org = "ballerina", name = "jballerina.java"},
{org = "ballerina", name = "lang.array"},
{org = "ballerina", name = "lang.error"}
]
modules = [
Expand All @@ -102,6 +132,7 @@ name = "mongodb"
version = "5.0.1"
dependencies = [
{org = "ballerina", name = "crypto"},
{org = "ballerina", name = "io"},
{org = "ballerina", name = "jballerina.java"},
{org = "ballerina", name = "log"},
{org = "ballerina", name = "test"}
Expand Down
32 changes: 19 additions & 13 deletions ballerina/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -91,26 +91,32 @@ task commitTomlFiles {
}

task startMongodbServer() {
doLast {
println("Starting mongodb server...")
exec {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine 'cmd', '/c', "docker-compose -f tests/resources/docker/docker-compose.yml up && exit %%ERRORLEVEL%%"
} else {
commandLine 'sh', '-c', "docker-compose -f tests/resources/docker/docker-compose.yml up -d"
gradle.taskGraph.whenReady { graph ->
if (graph.hasTask(":${packageName}-ballerina:test")) {
println("Starting mongodb server...")
exec {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine 'cmd', '/c', "docker-compose -f tests/resources/docker/docker-compose.yml up && exit %%ERRORLEVEL%%"
} else {
commandLine 'sh', '-c', "docker-compose -f tests/resources/docker/docker-compose.yml up -d"
}
}
}
}
}

task stopMongodbServer() {
doLast {
println("Stopping mongodb server...")
exec {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine 'cmd', '/c', "docker-compose -f tests/resources/docker/docker-compose.yml down && exit %%ERRORLEVEL%%"
} else {
commandLine 'sh', '-c', "docker-compose -f tests/resources/docker/docker-compose.yml down"
gradle.taskGraph.whenReady { graph ->
if (graph.hasTask(":${packageName}-ballerina:test")) {
println("Stopping mongodb server...")
exec {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine 'cmd', '/c', "docker-compose -f tests/resources/docker/docker-compose.yml down && exit %%ERRORLEVEL%%"
} else {
commandLine 'sh', '-c', "docker-compose -f tests/resources/docker/docker-compose.yml down"
}
}
}
}
}
Expand Down
10 changes: 6 additions & 4 deletions ballerina/collection.bal
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ public isolated client class Collection {
# + documents - The documents to insert
# + options - The options to apply to the operation
# + return - An error if the operation failed, otherwise nil
isolated remote function insertMany(record {|anydata...;|}[] documents, InsertManyOptions options = {}) returns Error? {
isolated remote function insertMany(record {|anydata...;|}[] documents, InsertManyOptions options = {})
returns Error? {
string[] documentString = documents.'map((doc) => doc.toJsonString());
return check insertMany(self, documentString, options);
}
Expand All @@ -67,7 +68,8 @@ public isolated client class Collection {
# + targetType - The type of the returned documents
# + return - A stream of documents which match the provided filter, or an error if the operation failed
isolated remote function find(map<json> filter = {}, FindOptions findOptions = {}, map<json>? projection = (),
typedesc<record {|anydata...;|}> targetType = <>) returns stream<targetType, error?>|Error = @java:Method {
typedesc<record {|anydata...;|}|record {|anydata...;|}[]> targetType = <>)
returns stream<targetType, error?>|Error = @java:Method {
'class: "io.ballerina.lib.mongodb.Collection"
} external;

Expand All @@ -80,7 +82,7 @@ public isolated client class Collection {
# + targetType - The type of the returned document
# + return - The document which matches the provided filter, or an error if the operation failed
isolated remote function findOne(map<json> filter = {}, FindOptions findOptions = {}, map<json>? projection = (),
typedesc<record {|anydata...;|}> targetType = <>) returns targetType|Error? = @java:Method {
typedesc<record {|anydata...;|}> targetType = <>) returns targetType|Error? = @java:Method {
'class: "io.ballerina.lib.mongodb.Collection"
} external;

Expand Down Expand Up @@ -196,7 +198,7 @@ public isolated client class Collection {
# + pipeline - The aggregation pipeline
# + targetType - The type of the returned documents
# + return - A stream of documents which match the provided pipeline, or an error if the operation failed
isolated remote function aggregate(map<json>[] pipeline, typedesc<anydata> targetType = <>)
isolated remote function aggregate(map<json>[] pipeline, typedesc<anydata|anydata[]> targetType = <>)
returns stream<targetType, error?>|Error = @java:Method {
'class: "io.ballerina.lib.mongodb.Collection"
} external;
Expand Down
52 changes: 52 additions & 0 deletions ballerina/tests/03_collection_tests.bal
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,58 @@ isolated function testComplexFind() returns error? {
check database->drop();
}

@test:Config {
groups: ["collection", "aggregate", "sort"]
}
isolated function testFindReturningArray() returns error? {
Database database = check mongoClient->getDatabase("testFindReturningArrayDB");
Collection tvShowsCollection = check database->getCollection("TvShows");
Collection directorsCollection = check database->getCollection("Directors");

TvShow tvShow1 = {title: "Breaking Bad", year: 2008, directorId: "1"};
TvShow tvShow2 = {title: "Game of Thrones", year: 2011, directorId: "2"};
TvShow tvShow3 = {title: "The Walking Dead", year: 2010, directorId: "3"};
TvShow tvShow4 = {title: "Better Call Saul", year: 2015, directorId: "1"};
check tvShowsCollection->insertMany([tvShow1, tvShow2, tvShow3, tvShow4]);

Director director1 = {id: "1", name: "Vince Gilligan"};
Director director2 = {id: "2", name: "David Benioff"};
Director director3 = {id: "3", name: "Frank Darabont"};
check directorsCollection->insertMany([director1, director2, director3]);

stream<record {
TvShow[] tvShows;
}, error?> result = check tvShowsCollection->aggregate([
{
\$group: {
_id: {directorId: "$directorId"},
tvShows: {
\$push: {
title: "$title",
year: "$year",
directorId: "$directorId"
}
}
}
},
{
\$sort: {
"tvShows.directorId": 1
}
}
]);
TvShow[][] actualResult = check from record {
TvShow[] tvShows;
} item in result
select item.tvShows;
TvShow[][] expectedResult = [[tvShow1, tvShow4], [tvShow2], [tvShow3]];
check result.close();
check tvShowsCollection->drop();
check directorsCollection->drop();
check database->drop();
test:assertEquals(actualResult, expectedResult);
}

@test:Config {
groups: ["collection", "insert", "aggregate", "projection"]
}
Expand Down
11 changes: 11 additions & 0 deletions ballerina/tests/types.bal
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,14 @@ type Author readonly & record {|
string name;
Book[] books;
|};

type TvShow record {|
string title;
int year;
string directorId;
|};

type Director record {|
string id;
string name;
|};
7 changes: 7 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
# Change Log

This file contains all the notable changes done to the Ballerina GraphQL package through the releases.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- [[#6377] Allow Returning Arrays from `find` and `aggregate` Operations](https://github.com/ballerina-platform/ballerina-standard-library/issues/6377)

## [5.0.0] - 2024-04-02

### Changed

- [[#5073] Revamping the connector with new Client, Database, and Collection model](https://github.com/ballerina-platform/ballerina-standard-library/issues/5073)
Loading