Skip to content

Commit

Permalink
fix:neo4j#2697 fix aggregation filter for duration
Browse files Browse the repository at this point in the history
  • Loading branch information
Andy2003 committed Jan 24, 2024
1 parent 608790d commit 7e129da
Showing 5 changed files with 161 additions and 39 deletions.
5 changes: 5 additions & 0 deletions .changeset/tricky-chairs-learn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@neo4j/graphql": patch
---

fix:#2697 fix aggregation filter for duration
Original file line number Diff line number Diff line change
@@ -23,15 +23,7 @@ import type { AggregationLogicalOperator } from "../../../factory/parsers/parse-

export class AggregationDurationFilter extends AggregationPropertyFilter {
protected getOperation(expr: Cypher.Expr): Cypher.ComparisonOp {
if (!this.aggregationOperator) {
return this.createDurationOperation({
operator: this.logicalOperator,
property: expr,
param: new Cypher.Param(this.comparisonValue),
});
}

return this.createBaseOperation({
return this.createDurationOperation({
operator: this.logicalOperator,
property: expr,
param: new Cypher.Param(this.comparisonValue),
125 changes: 125 additions & 0 deletions packages/graphql/tests/integration/issues/2697.int.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import type { Driver, Session } from "neo4j-driver";
import { graphql } from "graphql";
import Neo4j from "../neo4j";
import { Neo4jGraphQL } from "../../../src/classes";
import { UniqueType } from "../../utils/graphql-types";

describe("https://github.com/neo4j/graphql/issues/2697", () => {
let driver: Driver;
let neo4j: Neo4j;
let session: Session;
let typeDefs: string;

const typeMovie = new UniqueType("Movie");
const typeActor = new UniqueType("Actor");

let neoSchema: Neo4jGraphQL;

beforeAll(async () => {
neo4j = new Neo4j();
driver = await neo4j.getDriver();

typeDefs = `
type ${typeMovie.name} {
title: String
duration: Duration
actors: [${typeActor.name}!]! @relationship(type: "ACTED_IN", direction: IN, properties: "ActedIn")
}
type ${typeActor.name} {
name: String
movies: [${typeMovie.name}!]! @relationship(type: "ACTED_IN", direction: OUT, properties: "ActedIn")
}
interface ActedIn @relationshipProperties {
screenTime: Duration
}
`;

neoSchema = new Neo4jGraphQL({ typeDefs });
session = await neo4j.getSession();
await session.run(`
CREATE (t1:${typeMovie.name} { title: "Terminator 1", duration: duration("PT1H47M") }),
(t2:${typeMovie.name} { title: "Terminator 2", duration: duration("PT2H15M") }),
(arnold:${typeActor.name} { name: "Arnold"}),
(linda:${typeActor.name} { name: "Linda"}),
(arnold)-[:ACTED_IN { screenTime: duration("PT1H20M") }]->(t1),
(arnold)-[:ACTED_IN { screenTime: duration("PT2H01M") }]->(t2),
(linda)-[:ACTED_IN { screenTime: duration("PT30M") }]->(t1),
(linda)-[:ACTED_IN { screenTime: duration("PT20M") }]->(t2)
`);
});

afterAll(async () => {
await session.close();
await driver.close();
});

test("Aggregate on node duration", async () => {
const query = `
query {
${typeActor.plural}(where: { moviesAggregate: { node: {duration_AVERAGE_GT: "PT1H" } } } ) {
name
}
}
`;

const gqlResult = await graphql({
schema: await neoSchema.getSchema(),
source: query,
contextValue: neo4j.getContextValues(),
});

expect(gqlResult.errors).toBeUndefined();
expect((gqlResult as any).data[typeActor.plural]).toEqual([
{
name: "Arnold",
},
{
name: "Linda",
},
]);
});

test("Aggregate on edge duration", async () => {
const query = `
query {
${typeActor.plural}(where: { moviesAggregate: { edge: {screenTime_AVERAGE_GT: "PT1H" } } } ) {
name
}
}
`;

const gqlResult = await graphql({
schema: await neoSchema.getSchema(),
source: query,
contextValue: neo4j.getContextValues(),
});

expect(gqlResult.errors).toBeUndefined();
expect((gqlResult as any).data[typeActor.plural]).toEqual([
{
name: "Arnold",
},
]);
});
});
30 changes: 15 additions & 15 deletions packages/graphql/tests/tck/aggregations/where/edge/duration.test.ts
Original file line number Diff line number Diff line change
@@ -310,7 +310,7 @@ describe("Cypher Aggregations where edge with Duration", () => {
CALL {
WITH this
MATCH (this)<-[this0:LIKES]-(this1:User)
RETURN avg(this0.someDuration) = $param0 AS var2
RETURN (datetime() + avg(this0.someDuration)) = (datetime() + $param0) AS var2
}
WITH *
WHERE var2 = true
@@ -351,7 +351,7 @@ describe("Cypher Aggregations where edge with Duration", () => {
CALL {
WITH this
MATCH (this)<-[this0:LIKES]-(this1:User)
RETURN avg(this0.someDuration) > $param0 AS var2
RETURN (datetime() + avg(this0.someDuration)) > (datetime() + $param0) AS var2
}
WITH *
WHERE var2 = true
@@ -392,7 +392,7 @@ describe("Cypher Aggregations where edge with Duration", () => {
CALL {
WITH this
MATCH (this)<-[this0:LIKES]-(this1:User)
RETURN avg(this0.someDuration) >= $param0 AS var2
RETURN (datetime() + avg(this0.someDuration)) >= (datetime() + $param0) AS var2
}
WITH *
WHERE var2 = true
@@ -433,7 +433,7 @@ describe("Cypher Aggregations where edge with Duration", () => {
CALL {
WITH this
MATCH (this)<-[this0:LIKES]-(this1:User)
RETURN avg(this0.someDuration) < $param0 AS var2
RETURN (datetime() + avg(this0.someDuration)) < (datetime() + $param0) AS var2
}
WITH *
WHERE var2 = true
@@ -474,7 +474,7 @@ describe("Cypher Aggregations where edge with Duration", () => {
CALL {
WITH this
MATCH (this)<-[this0:LIKES]-(this1:User)
RETURN avg(this0.someDuration) <= $param0 AS var2
RETURN (datetime() + avg(this0.someDuration)) <= (datetime() + $param0) AS var2
}
WITH *
WHERE var2 = true
@@ -515,7 +515,7 @@ describe("Cypher Aggregations where edge with Duration", () => {
CALL {
WITH this
MATCH (this)<-[this0:LIKES]-(this1:User)
RETURN min(this0.someDuration) = $param0 AS var2
RETURN (datetime() + min(this0.someDuration)) = (datetime() + $param0) AS var2
}
WITH *
WHERE var2 = true
@@ -556,7 +556,7 @@ describe("Cypher Aggregations where edge with Duration", () => {
CALL {
WITH this
MATCH (this)<-[this0:LIKES]-(this1:User)
RETURN min(this0.someDuration) > $param0 AS var2
RETURN (datetime() + min(this0.someDuration)) > (datetime() + $param0) AS var2
}
WITH *
WHERE var2 = true
@@ -597,7 +597,7 @@ describe("Cypher Aggregations where edge with Duration", () => {
CALL {
WITH this
MATCH (this)<-[this0:LIKES]-(this1:User)
RETURN min(this0.someDuration) >= $param0 AS var2
RETURN (datetime() + min(this0.someDuration)) >= (datetime() + $param0) AS var2
}
WITH *
WHERE var2 = true
@@ -638,7 +638,7 @@ describe("Cypher Aggregations where edge with Duration", () => {
CALL {
WITH this
MATCH (this)<-[this0:LIKES]-(this1:User)
RETURN min(this0.someDuration) < $param0 AS var2
RETURN (datetime() + min(this0.someDuration)) < (datetime() + $param0) AS var2
}
WITH *
WHERE var2 = true
@@ -679,7 +679,7 @@ describe("Cypher Aggregations where edge with Duration", () => {
CALL {
WITH this
MATCH (this)<-[this0:LIKES]-(this1:User)
RETURN min(this0.someDuration) <= $param0 AS var2
RETURN (datetime() + min(this0.someDuration)) <= (datetime() + $param0) AS var2
}
WITH *
WHERE var2 = true
@@ -720,7 +720,7 @@ describe("Cypher Aggregations where edge with Duration", () => {
CALL {
WITH this
MATCH (this)<-[this0:LIKES]-(this1:User)
RETURN max(this0.someDuration) = $param0 AS var2
RETURN (datetime() + max(this0.someDuration)) = (datetime() + $param0) AS var2
}
WITH *
WHERE var2 = true
@@ -761,7 +761,7 @@ describe("Cypher Aggregations where edge with Duration", () => {
CALL {
WITH this
MATCH (this)<-[this0:LIKES]-(this1:User)
RETURN max(this0.someDuration) > $param0 AS var2
RETURN (datetime() + max(this0.someDuration)) > (datetime() + $param0) AS var2
}
WITH *
WHERE var2 = true
@@ -802,7 +802,7 @@ describe("Cypher Aggregations where edge with Duration", () => {
CALL {
WITH this
MATCH (this)<-[this0:LIKES]-(this1:User)
RETURN max(this0.someDuration) >= $param0 AS var2
RETURN (datetime() + max(this0.someDuration)) >= (datetime() + $param0) AS var2
}
WITH *
WHERE var2 = true
@@ -843,7 +843,7 @@ describe("Cypher Aggregations where edge with Duration", () => {
CALL {
WITH this
MATCH (this)<-[this0:LIKES]-(this1:User)
RETURN max(this0.someDuration) < $param0 AS var2
RETURN (datetime() + max(this0.someDuration)) < (datetime() + $param0) AS var2
}
WITH *
WHERE var2 = true
@@ -884,7 +884,7 @@ describe("Cypher Aggregations where edge with Duration", () => {
CALL {
WITH this
MATCH (this)<-[this0:LIKES]-(this1:User)
RETURN max(this0.someDuration) <= $param0 AS var2
RETURN (datetime() + max(this0.someDuration)) <= (datetime() + $param0) AS var2
}
WITH *
WHERE var2 = true
Loading

0 comments on commit 7e129da

Please sign in to comment.