Skip to content

Apoc usage

angrykoala edited this page Jul 5, 2022 · 44 revisions

This page documents current usage of apoc and any known alternative

Location Procedure File Notes
CypherResolver runFirstColumn src/schema/resolvers/field/cypher.ts -
Aggregate Where runFirstColumn src/translate/create-aggregate-where-and-params.ts -
CreateProjectionAndParams runFirstColumn src/translate/create-projection-and-params.ts Multiple instances
Top level aggregate runFirstColumn src/translate/translate-aggregate.ts -
Field aggregations runFirstColumn src/translate/field-aggregations/create-field-aggregation.ts Multiple instances
Query Points runFirstColumn src/translate/projection/elements/create-point-element.ts -
Create Element Where runFirstColumn src/translate/where/create-element-where-and-params.ts Multiple Instances

Run First Column

Cypher Resolver

Used for @cypher directive.

Example

Schema

type Movie {
  id: ID
  title: String
  topActor: Actor
    @cypher(
      statement: """
          MATCH (a:Person)-[]-(this) 
          RETURN a
      """
    )
}

type Actor {
  name: String
}

Query

{
  movies {
    title
    topActor {
      name
    }
  }
}

Cypher

MATCH (this:Movie)
RETURN this { 
    .title, 
    topActor: head([this_topActor IN apoc.cypher.runFirstColumn("MATCH (a:Person)-[]-(this) 
            RETURN a", {this: this}, false) | this_topActor { .name }]) 
} as this

Alternative Cypher

MATCH(m:Movie)
CALL {
    WITH m
    WITH m as this
    MATCH (a:Person)-[]-(this)
    RETURN a
}
WITH m, collect(a) as projection
RETURN m {.title, topActor: head([this_topActor IN projection | this_topActor { .name }]) }

Considerations

  • Return multiple items in an array vs a single by using head in the projection.
  • We need to keep track of subqueries for projection.

Aggregate Where

Use for aggregation where (e.g. count)

Example

Schema

type User {
	name: String!
}

type Post {
	content: String!
	likes: [User!]! @relationship(type: "LIKES", direction: IN)
}

Query

{
	posts(where: { likesAggregate: { count: 10 } }) {
		content
	}
}

Cypher

MATCH (this:Post)
WHERE apoc.cypher.runFirstColumn(" MATCH (this)<-[this_likesAggregate_edge:LIKES]-(this_likesAggregate_node:User)
RETURN count(this_likesAggregate_node) = $this_likesAggregate_count
", { this: this, this_likesAggregate_count: $this_likesAggregate_count }, false )
RETURN this { .content } as this

Alternative Cypher

MATCH(this:Post)
CALL {
    WITH this
    MATCH(this)<-[:LIKES]-(u:User)
    RETURN count(u) as agg_count
}
WITH *
WHERE agg_count=10
RETURN m {.title} as this

Considerations

  • Keep track of subqueries for where statement.

Query Points

Example

Schema

type PointContainer {
  point: Point
}

Query

{
  pointContainers(where: { point: { longitude: 1.0, latitude: 2.0 } }) {
    point {
      longitude
      latitude
      crs
    }
  }
}

Cypher

MATCH (this:PointContainer)
WHERE this.point = point($this_point)
RETURN this { point: apoc.cypher.runFirstColumn('RETURN
            CASE this.point IS NOT NULL
            	WHEN true THEN { point: this.point, crs: this.point.crs }
            	ELSE NULL
            END AS result',{ this: this },false) 
} as this

Alternative Cypher

MATCH(this:PointContainer)
WITH this,
CASE this.point IS NOT NULL
  WHEN true THEN {point: this.point, crs: this.point.crs}
  ELSE NULL
END AS this_point
RETURN this {.name, point: this_point} as this

Considerations

  • We need to keep track of subqueries for projection.

Create Element Where

WIP

Clone this wiki locally