Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
08-27-2018 05:59 PM
I have been working with the most recent GRANDstack starter application. I have gotten hung up on how to create a more complicated traversal as shown here: https://grandstack.io/docs/neo4j-graphql-js.html
type Movie {
movieId: ID!
title: String
year: Int
plot: String
poster: String
imdbRating: Float
similar(first: Int = 3, offset: Int = 0): [Movie] @cypher(statement: "MATCH (this)-[:IN_GENRE]->(:Genre)<-[:IN_GENRE]-(o:Movie) RETURN o")
degree: Int @cypher(statement: "RETURN SIZE((this)-->())")
actors(first: Int = 3, offset: Int = 0): [Actor] @relation(name: "ACTED_IN", direction:"IN")
}
type Actor {
id: ID!
name: String
movies: [Movie]
}
type Query {
Movie(id: ID, title: String, year: Int, imdbRating: Float, first: Int, offset: Int): [Movie]
}
';
and here
{
Movie(title: "River Runs Through It, A") {
title
year
imdbRating
actors {
name
}
similar(first: 3) {
title
}
}
}
When attempting to use a similar step as shown by actors
I am failing to pull in the correct data associated. I am using some of my own data I have been inserting into the GRANDstack starter application, but the concept is transferable. What are the caveats and key concepts that I need to consider to make a similar traversal?
For use in the GRANDstack application, how would I need to reference that "subquery" within the context of the starter application framework (i.e. my equivalent actors
doesn't show up)?
Solved! Go to Solution.
06-13-2019 05:11 AM
You probably already solved that riddle ( the meaning of (first: 10, offset: 0)), but for the sake of other readers let's clarify it.
The first
keyword means that at most 10 items are fetched.
With offset
you determine where to start in the whole result set.
Read more about it
08-27-2018 11:17 PM
Sorry, you have to provide more detail. Don't understand what you're looking for. Can you share your attempt, i.e. how far you've come and how it fails?
08-28-2018 04:27 AM
Below is what I have in graphql-schema.js
:
import { neo4jgraphql } from "neo4j-graphql-js";
export const typeDefs = `
type User {
id: ID!
name: String
friends(first: Int = 10, offset: Int = 0): [User] @relation(name: "FRIENDS", direction: "BOTH")
reviews(first: Int = 10, offset: Int = 0): [Review] @relation(name: "WROTE", direction: "OUT")
avgStars: Float @cypher(statement: "MATCH (this)-[:WROTE]->(r:Review) RETURN toFloat(avg(r.stars))")
numReviews: Int @cypher(statement: "MATCH (this)-[:WROTE]->(r:Review) RETURN COUNT(r)")
totalStars: Int @cypher(statement: "MATCH (this)-[:WROTE]->(r:Review) RETURN SUM(r.stars)")
}
type Business {
id: ID!
name: String
address: String
city: String
state: String
reviews(first: Int = 10, offset: Int = 0): [Review] @relation(name: "REVIEWS", direction: "IN")
categories(first: Int = 10, offset: Int =0): [Category] @relation(name: "IN_CATEGORY", direction: "OUT")
numReviews: Int @cypher(statement: "MATCH (this)<-[:REVIEWS]-(r:Review) RETURN count(r)")
avgStars: Float @cypher(statement: "MATCH (this)<-[:REVIEWS]-(r:Review) WHERE r.stars IS NOT NULL RETURN toFloat(avg(r.stars))")
category: String @cypher(statement: "MATCH (this)-[:IN_CATEGORY]->(r:Category) RETURN r.name")
}
type Review {
id: ID!
stars: Int
text: String
business: Business @relation(name: "REVIEWS", direction: "OUT")
user: User @relation(name: "WROTE", direction: "IN")
business_name: String @cypher(statement: "MATCH (this)-[:REVIEWS]->(r:Business) RETURN r.name")
user_name: String @cypher(statement: "MATCH (this)<-[:WROTE]-(r:User) RETURN r.name")
}
type Category {
name: ID!
businesses(first: Int = 10, offset: Int = 0): [Business] @relation(name: "IN_CATEGORY", direction: "IN")
}
type Ring {
id: ID!
name: String
divisions(first: Int = 10, offset: Int = 0): [Division] @relation(name: "OCCURS_IN", direction: "IN")
}
type Division {
id: ID!
name: String
div: String
sex: String
rank: String
ageLow: Int
ageHigh: Int
status: String
}
type Person {
id: ID!
name: String
sex: String
age: Int
rank: String
}
type Query {
users(id: ID, name: String, first: Int = 10, offset: Int = 0): [User]
businesses(id: ID, name: String, first: Int = 10, offset: Int = 0): [Business]
reviews(id: ID, stars: Int, first: Int = 10, offset: Int = 0): [Review]
category(name: ID!): Category
usersBySubstring(substring: String, first: Int = 10, offset: Int = 0): [User] @cypher(statement: "MATCH (u:User) WHERE u.name CONTAINS $substring RETURN u")
divisions(id: ID, name: String, div: String, sex: String, rank: String, ageLow: Int, ageHigh: Int, status: String, first: Int, offset: Int): [Division]
rings(id: ID, name: String, first: Int = 10, offset: Int = 0): [Ring]
competitors(name: String): [Person]
judges(name: String): [Person] @cypher(statement: "MATCH (p:Person) WHERE p.age >=18 AND p.rank CONTAINS 'Black Belt' RETURN p")
}
`;
export const resolvers = {
Query: {
users: neo4jgraphql,
businesses: neo4jgraphql,
reviews: neo4jgraphql,
category: neo4jgraphql,
usersBySubstring: neo4jgraphql,
divisions: neo4jgraphql,
rings: neo4jgraphql,
competitors: neo4jgraphql,
judges: neo4jgraphql
}
};
Following the same general format as UserList.js
, 'BusinessList.js, etc., I created
RingList.js, in which I added a material card that expands to show a table. The card title is linked to the Query
ringsin which I would like to query all
divisionsassociated with that ring. It is the "nested or subquery"
divisionsthat I cannot seem to get working correctly. I have tried multiple things. As it is shown here now the
and
material components are associated/mapped with the
ringquery to pull each ring name. Then in
08-29-2018 12:20 PM
Hey Michael -
First, can you confirm the GraphQL query works and returns the expected results when running in GraphQL Playground? Just want to make sure the React component is getting the data it expects.
{
rings(first: 10, offset: 0) {
id
name
divisions(first: 10, offset: 0) {
id
name
div
sex
rank
ageLow
ageHigh
status
}
}
}
08-29-2018 12:59 PM
When running that query in the GraphQL playground I do get results that appear to match the expected query results. I am uncertain if I need to use a second "mapping" when populating the table, but even attempting using n.divisions.name
doesn't appear to work since I have already mapped data.rings
to n
. So I have tried the adding the second mapping, but can't seem to figure out where it is getting tripped up.
08-29-2018 02:14 PM
data.rings
is an array, so calling data.rings.map
allows you to iterate over each element of the rings
array (creating a table row for each element). Similarly, divisions
is also an array, so you can map over the divisions
array in a nested fashion as you are iterating over rings, and do some operation for each division (like adding a row for each division in the table). But calling n.divisions.name
will throw an error because divisions
is an array, not an object.
For example, something like this will log all division names for each ring:
data.rings.map( r => {
console.log("Ring: " + r.name);
r.divisions.map( d => {
console.log("Division: " + d.name);
})
})
You want to use a similar concept for adding table rows.
08-29-2018 05:32 PM
Brilliant! That was what I needed. I was getting stuck on the mapping. I wasn't utilizing the variable for the data.rings
when mapping divisions
.
Thank you very much!
08-30-2018 09:04 AM
Cool - glad that helped!
08-30-2018 09:44 AM
One piece of clarification that I still don't understand is the use of
(first: 10, offset: 0)
in the schema and when querying. Is this required, or can I choose to not specify these parameters?
06-13-2019 05:11 AM
You probably already solved that riddle ( the meaning of (first: 10, offset: 0)), but for the sake of other readers let's clarify it.
The first
keyword means that at most 10 items are fetched.
With offset
you determine where to start in the whole result set.
Read more about it
All the sessions of the conference are now available online