From 7d9cbb3ce939b5d943a8eed0bd3d97087066364a Mon Sep 17 00:00:00 2001 From: roschaefer Date: Tue, 3 Mar 2020 19:06:55 +0100 Subject: [PATCH 1/2] perf(neo4j): Improve currentUser read performance --- .../src/schema/resolvers/user_management.js | 26 ++++++++++++++--- backend/src/schema/types/type/User.gql | 4 +-- webapp/graphql/User.js | 21 ++++++++++++++ webapp/store/auth.js | 28 ++----------------- 4 files changed, 47 insertions(+), 32 deletions(-) diff --git a/backend/src/schema/resolvers/user_management.js b/backend/src/schema/resolvers/user_management.js index 4d40a6f63..2014b01b8 100644 --- a/backend/src/schema/resolvers/user_management.js +++ b/backend/src/schema/resolvers/user_management.js @@ -12,10 +12,28 @@ export default { isLoggedIn: (_, args, { driver, user }) => { return Boolean(user && user.id) }, - currentUser: async (object, params, ctx, resolveInfo) => { - if (!ctx.user) return null - const user = await neode.find('User', ctx.user.id) - return user.toJson() + currentUser: async (object, params, context, resolveInfo) => { + const { user, driver } = context + if (!user) return null + const session = driver.session() + const currentUserTransactionPromise = session.readTransaction(async transaction => { + const result = await transaction.run( + ` + MATCH (user:User {id: $id}) + WITH user, [(user)<-[:OWNED_BY]-(medium:SocialMedia) | properties(medium) ] as media + RETURN user {.*, socialMedia: media } as user + `, + { id: user.id }, + ) + log(result) + return result.records.map(record => record.get('user')) + }) + try { + const [currentUser] = await currentUserTransactionPromise + return currentUser + } finally { + session.close() + } }, }, Mutation: { diff --git a/backend/src/schema/types/type/User.gql b/backend/src/schema/types/type/User.gql index 948d8e7d3..e83408f75 100644 --- a/backend/src/schema/types/type/User.gql +++ b/backend/src/schema/types/type/User.gql @@ -97,14 +97,14 @@ type User { contributions: [Post]! @relation(name: "WROTE", direction: "OUT") contributionsCount: Int! @cypher( statement: """ - MATCH (this)-[: WROTE]->(r: Post) + MATCH (this)-[:WROTE]->(r:Post) WHERE NOT r.deleted = true AND NOT r.disabled = true RETURN COUNT(r) """ ) comments: [Comment]! @relation(name: "WROTE", direction: "OUT") - commentedCount: Int! @cypher(statement: "MATCH (this)-[: WROTE]->(: Comment)-[: COMMENTS]->(p: Post) WHERE NOT p.deleted = true AND NOT p.disabled = true RETURN COUNT(DISTINCT(p))") + commentedCount: Int! @cypher(statement: "MATCH (this)-[:WROTE]->(:Comment)-[:COMMENTS]->(p:Post) WHERE NOT p.deleted = true AND NOT p.disabled = true RETURN COUNT(DISTINCT(p))") shouted: [Post]! @relation(name: "SHOUTED", direction: "OUT") shoutedCount: Int! @cypher(statement: "MATCH (this)-[: SHOUTED]->(r: Post) WHERE NOT r.deleted = true AND NOT r.disabled = true RETURN COUNT(DISTINCT r)") diff --git a/webapp/graphql/User.js b/webapp/graphql/User.js index fb0c4dddd..02f0909e3 100644 --- a/webapp/graphql/User.js +++ b/webapp/graphql/User.js @@ -258,3 +258,24 @@ export const checkSlugAvailableQuery = gql` } } ` + +export const currentUserQuery = gql` + ${userFragment} + query { + currentUser { + ...user + email + role + about + locationName + locale + allowEmbedIframes + showShoutsPublicly + termsAndConditionsAgreedVersion + socialMedia { + id + url + } + } + } +` diff --git a/webapp/store/auth.js b/webapp/store/auth.js index d0e68306d..072c13bd8 100644 --- a/webapp/store/auth.js +++ b/webapp/store/auth.js @@ -1,5 +1,6 @@ import gql from 'graphql-tag' import { VERSION } from '~/constants/terms-and-conditions-version.js' +import { currentUserQuery } from '~/graphql/User' export const state = () => { return { @@ -72,32 +73,7 @@ export const actions = { const client = this.app.apolloProvider.defaultClient const { data: { currentUser }, - } = await client.query({ - query: gql` - query { - currentUser { - id - name - slug - email - avatar - role - about - locationName - locale - contributionsCount - commentedCount - allowEmbedIframes - showShoutsPublicly - termsAndConditionsAgreedVersion - socialMedia { - id - url - } - } - } - `, - }) + } = await client.query({ query: currentUserQuery }) if (!currentUser) return dispatch('logout') commit('SET_USER', currentUser) return currentUser From 628ec2a188fe0a39291ce27d2e07354fb5fa9375 Mon Sep 17 00:00:00 2001 From: roschaefer Date: Wed, 4 Mar 2020 15:17:31 +0100 Subject: [PATCH 2/2] Follow @mogge's PR review --- backend/src/schema/types/type/User.gql | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/src/schema/types/type/User.gql b/backend/src/schema/types/type/User.gql index e83408f75..4c3555049 100644 --- a/backend/src/schema/types/type/User.gql +++ b/backend/src/schema/types/type/User.gql @@ -27,7 +27,7 @@ type User { id: ID! actorId: String name: String - email: String! @cypher(statement: "MATCH (this)-[: PRIMARY_EMAIL]->(e: EmailAddress) RETURN e.email") + email: String! @cypher(statement: "MATCH (this)-[:PRIMARY_EMAIL]->(e:EmailAddress) RETURN e.email") slug: String! avatar: String coverImg: String @@ -38,7 +38,7 @@ type User { invitedBy: User @relation(name: "INVITED", direction: "IN") invited: [User] @relation(name: "INVITED", direction: "OUT") - location: Location @cypher(statement: "MATCH (this)-[: IS_IN]->(l: Location) RETURN l") + location: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l") locationName: String about: String socialMedia: [SocialMedia]! @relation(name: "OWNED_BY", direction: "IN") @@ -53,13 +53,13 @@ type User { showShoutsPublicly: Boolean locale: String friends: [User]! @relation(name: "FRIENDS", direction: "BOTH") - friendsCount: Int! @cypher(statement: "MATCH (this)<-[: FRIENDS]->(r: User) RETURN COUNT(DISTINCT r)") + friendsCount: Int! @cypher(statement: "MATCH (this)<-[:FRIENDS]->(r:User) RETURN COUNT(DISTINCT r)") following: [User]! @relation(name: "FOLLOWS", direction: "OUT") - followingCount: Int! @cypher(statement: "MATCH (this)-[: FOLLOWS]->(r: User) RETURN COUNT(DISTINCT r)") + followingCount: Int! @cypher(statement: "MATCH (this)-[:FOLLOWS]->(r:User) RETURN COUNT(DISTINCT r)") followedBy: [User]! @relation(name: "FOLLOWS", direction: "IN") - followedByCount: Int! @cypher(statement: "MATCH (this)<-[: FOLLOWS]-(r: User) RETURN COUNT(DISTINCT r)") + followedByCount: Int! @cypher(statement: "MATCH (this)<-[:FOLLOWS]-(r:User) RETURN COUNT(DISTINCT r)") # Is the currently logged in user following that user? followedByCurrentUser: Boolean! @cypher( @@ -107,12 +107,12 @@ type User { commentedCount: Int! @cypher(statement: "MATCH (this)-[:WROTE]->(:Comment)-[:COMMENTS]->(p:Post) WHERE NOT p.deleted = true AND NOT p.disabled = true RETURN COUNT(DISTINCT(p))") shouted: [Post]! @relation(name: "SHOUTED", direction: "OUT") - shoutedCount: Int! @cypher(statement: "MATCH (this)-[: SHOUTED]->(r: Post) WHERE NOT r.deleted = true AND NOT r.disabled = true RETURN COUNT(DISTINCT r)") + shoutedCount: Int! @cypher(statement: "MATCH (this)-[:SHOUTED]->(r:Post) WHERE NOT r.deleted = true AND NOT r.disabled = true RETURN COUNT(DISTINCT r)") categories: [Category]! @relation(name: "CATEGORIZED", direction: "OUT") badges: [Badge]! @relation(name: "REWARDED", direction: "IN") - badgesCount: Int! @cypher(statement: "MATCH (this)<-[: REWARDED]-(r: Badge) RETURN COUNT(r)") + badgesCount: Int! @cypher(statement: "MATCH (this)<-[:REWARDED]-(r:Badge) RETURN COUNT(r)") emotions: [EMOTED] }