这是indexloc提供的服务,不要输入任何密码
Skip to content

serialize aggregate results as simple instead of extended json #96

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

Merged
Merged
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ This changelog documents the changes between release versions.

## [Unreleased]
- Accept predicate arguments in native mutations and native queries ([#92](https://github.com/hasura/ndc-mongodb/pull/92))
- Serialize aggregate results as simple JSON (instead of Extended JSON) for
consistency with non-aggregate result serialization ([#96](https://github.com/hasura/ndc-mongodb/pull/96))

## [1.0.0] - 2024-07-09

Expand Down
39 changes: 39 additions & 0 deletions crates/integration-tests/src/tests/aggregation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use insta::assert_yaml_snapshot;
use serde_json::json;

use crate::graphql_query;

#[tokio::test]
async fn runs_aggregation_over_top_level_fields() -> anyhow::Result<()> {
assert_yaml_snapshot!(
graphql_query(
r#"
query($albumId: Int!) {
track(order_by: { id: Asc }, where: { albumId: { _eq: $albumId } }) {
milliseconds
unitPrice
}
trackAggregate(
filter_input: { order_by: { id: Asc }, where: { albumId: { _eq: $albumId } } }
) {
_count
milliseconds {
_avg
_max
_min
_sum
}
unitPrice {
_count
_count_distinct
}
}
}
"#
)
.variables(json!({ "albumId": 9 }))
.run()
.await?
);
Ok(())
}
1 change: 1 addition & 0 deletions crates/integration-tests/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// rust-analyzer.cargo.allFeatures = true
//

mod aggregation;
mod basic;
mod local_relationship;
mod native_mutation;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
source: crates/integration-tests/src/tests/aggregation.rs
expression: "graphql_query(r#\"\n query($albumId: Int!) {\n track(order_by: { id: Asc }, where: { albumId: { _eq: $albumId } }) {\n milliseconds\n unitPrice\n }\n trackAggregate(\n filter_input: { order_by: { id: Asc }, where: { albumId: { _eq: $albumId } } }\n ) {\n _count\n milliseconds {\n _avg\n _max\n _min\n _sum\n }\n unitPrice {\n _count\n _count_distinct\n }\n }\n }\n \"#).variables(json!({\n \"albumId\": 9\n })).run().await?"
---
data:
track:
- milliseconds: 221701
unitPrice: "0.99"
- milliseconds: 436453
unitPrice: "0.99"
- milliseconds: 374543
unitPrice: "0.99"
- milliseconds: 322925
unitPrice: "0.99"
- milliseconds: 288208
unitPrice: "0.99"
- milliseconds: 308035
unitPrice: "0.99"
- milliseconds: 369345
unitPrice: "0.99"
- milliseconds: 350197
unitPrice: "0.99"
trackAggregate:
_count: 8
milliseconds:
_avg: 333925.875
_max: 436453
_min: 221701
_sum: 2671407
unitPrice:
_count: 8
_count_distinct: 1
errors: ~
36 changes: 14 additions & 22 deletions crates/mongodb-agent-common/src/query/foreach.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,25 +261,17 @@ mod tests {
]);

let expected_response = query_response()
.row_set(
row_set()
.aggregates([("count", json!({ "$numberInt": "2" }))])
.rows([
[
("albumId", json!(1)),
("title", json!("For Those About To Rock We Salute You")),
],
[("albumId", json!(4)), ("title", json!("Let There Be Rock"))],
]),
)
.row_set(
row_set()
.aggregates([("count", json!({ "$numberInt": "2" }))])
.rows([
[("albumId", json!(2)), ("title", json!("Balls to the Wall"))],
[("albumId", json!(3)), ("title", json!("Restless and Wild"))],
]),
)
.row_set(row_set().aggregates([("count", json!(2))]).rows([
[
("albumId", json!(1)),
("title", json!("For Those About To Rock We Salute You")),
],
[("albumId", json!(4)), ("title", json!("Let There Be Rock"))],
]))
.row_set(row_set().aggregates([("count", json!(2))]).rows([
[("albumId", json!(2)), ("title", json!("Balls to the Wall"))],
[("albumId", json!(3)), ("title", json!("Restless and Wild"))],
]))
.build();

let db = mock_aggregate_response_for_pipeline(
Expand Down Expand Up @@ -307,7 +299,7 @@ mod tests {
);

let result = execute_query_request(db, &music_config(), query_request).await?;
assert_eq!(expected_response, result);
assert_eq!(result, expected_response);

Ok(())
}
Expand Down Expand Up @@ -370,8 +362,8 @@ mod tests {
]);

let expected_response = query_response()
.row_set(row_set().aggregates([("count", json!({ "$numberInt": "2" }))]))
.row_set(row_set().aggregates([("count", json!({ "$numberInt": "2" }))]))
.row_set(row_set().aggregates([("count", json!(2))]))
.row_set(row_set().aggregates([("count", json!(2))]))
.build();

let db = mock_aggregate_response_for_pipeline(
Expand Down
7 changes: 2 additions & 5 deletions crates/mongodb-agent-common/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,7 @@ mod tests {
.into();

let expected_response = row_set()
.aggregates([
("count", json!({ "$numberInt": "11" })),
("avg", json!({ "$numberInt": "3" })),
])
.aggregates([("count", json!(11)), ("avg", json!(3))])
.into_response();

let expected_pipeline = bson!([
Expand Down Expand Up @@ -175,7 +172,7 @@ mod tests {
.into();

let expected_response = row_set()
.aggregates([("avg", json!({ "$numberDouble": "3.1" }))])
.aggregates([("avg", json!(3.1))])
.row([("student_gpa", 3.1)])
.into_response();

Expand Down
2 changes: 1 addition & 1 deletion crates/mongodb-agent-common/src/query/relations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ mod tests {
"students_aggregate",
json!({
"aggregates": {
"aggregate_count": { "$numberInt": "2" }
"aggregate_count": 2
}
}),
)])
Expand Down
30 changes: 23 additions & 7 deletions crates/mongodb-agent-common/src/query/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,10 @@ fn serialize_row_set_with_aggregates(
fn serialize_aggregates(
mode: ExtendedJsonMode,
path: &[&str],
_query_aggregates: &IndexMap<ndc_models::FieldName, Aggregate>,
query_aggregates: &IndexMap<ndc_models::FieldName, Aggregate>,
value: Bson,
) -> Result<IndexMap<ndc_models::FieldName, serde_json::Value>> {
let aggregates_type = type_for_aggregates()?;
let aggregates_type = type_for_aggregates(query_aggregates);
let json = bson_to_json(mode, &aggregates_type, value)?;

// The NDC type uses an IndexMap for aggregate values; we need to convert the map
Expand Down Expand Up @@ -184,8 +184,8 @@ fn type_for_row_set(
) -> Result<Type> {
let mut type_fields = BTreeMap::new();

if aggregates.is_some() {
type_fields.insert("aggregates".into(), type_for_aggregates()?);
if let Some(aggregates) = aggregates {
type_fields.insert("aggregates".into(), type_for_aggregates(aggregates));
}

if let Some(query_fields) = fields {
Expand All @@ -199,9 +199,25 @@ fn type_for_row_set(
}))
}

// TODO: infer response type for aggregates MDB-130
fn type_for_aggregates() -> Result<Type> {
Ok(Type::Scalar(MongoScalarType::ExtendedJSON))
fn type_for_aggregates(query_aggregates: &IndexMap<ndc_models::FieldName, Aggregate>) -> Type {
let fields = query_aggregates
.iter()
.map(|(field_name, aggregate)| {
(
field_name.to_string().into(),
match aggregate {
Aggregate::ColumnCount { .. } => {
Type::Scalar(MongoScalarType::Bson(mongodb_support::BsonScalarType::Int))
}
Aggregate::StarCount => {
Type::Scalar(MongoScalarType::Bson(mongodb_support::BsonScalarType::Int))
}
Aggregate::SingleColumn { result_type, .. } => result_type.clone(),
},
)
})
.collect();
Type::Object(ObjectType { fields, name: None })
}

fn type_for_row(
Expand Down
Loading