From ee60bf7e15c790cbed82116a2336e4aa4e69f5fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Wed, 11 Mar 2020 11:03:03 +0100 Subject: [PATCH] Refactored the Cypher query for notifications --- backend/src/schema/resolvers/notifications.js | 85 +++++++- .../schema/resolvers/notifications.spec.js | 183 +++++++++--------- backend/src/schema/types/type/FILED.gql | 2 +- backend/src/schema/types/type/NOTIFIED.gql | 3 +- webapp/graphql/Moderation.js | 1 - 5 files changed, 172 insertions(+), 102 deletions(-) diff --git a/backend/src/schema/resolvers/notifications.js b/backend/src/schema/resolvers/notifications.js index ac038b494..2ddc137ba 100644 --- a/backend/src/schema/resolvers/notifications.js +++ b/backend/src/schema/resolvers/notifications.js @@ -45,25 +45,94 @@ export default { const readTxResultPromise = session.readTransaction(async transaction => { const notificationsTransactionResponse = await transaction.run( ` + // Wolle MATCH (resource)-[notification:NOTIFIED]->(user:User {id:$id}) + // WHERE + // ((labels(resource)[0] in ["Post", "Comment"] AND NOT resource.deleted AND NOT resource.disabled) + // OR labels(resource)[0] in ["Report"]) + // ${whereClause} + // WITH user, notification, resource, + // [(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors, + // [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post {.*, author: properties(author)} ] AS posts, + // [(reportedResource)<-[:BELONGS_TO]-(resource)<-[file:FILED]-(user) | file {.*, reportedResource: apoc.map.merge(properties(reportedResource), {__typename: labels(reportedResource)[0]})} ] AS files + // WITH resource, user, notification, authors, posts, files, + // resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0], filed: files, resource: files[0].reportedResource} AS finalResource + // RETURN notification {.*, from: finalResource, to: properties(user)} + // ${orderByClause} + // ${offset} ${limit} + MATCH (resource)-[notification:NOTIFIED]->(user:User {id:$id}) WHERE ((labels(resource)[0] in ["Post", "Comment"] AND NOT resource.deleted AND NOT resource.disabled) OR labels(resource)[0] in ["Report"]) ${whereClause} - WITH user, notification, resource, - [(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors, - [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post {.*, author: properties(author)} ] AS posts, - [(reportedResource)<-[:BELONGS_TO]-(resource)<-[file:FILED]-(user) | file {.*, reportedResource: apoc.map.merge(properties(reportedResource), {__typename: labels(reportedResource)[0]})} ] AS files - WITH resource, user, notification, authors, posts, files, - resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0], filed: files, resource: files[0].reportedResource} AS finalResource - RETURN notification {.*, from: finalResource, to: properties(user)} + CALL apoc.case( + [ + labels(resource)[0] = "Post", ' + MATCH (resource)<-[:WROTE]-(author:User) + RETURN resource {.*, __typename: labels(resource)[0], author: author} AS finalResource', + labels(resource)[0] = "Comment", ' + MATCH (author:User)-[:WROTE]->(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(postAuthor:User) + RETURN resource {.*, __typename: labels(resource)[0], author: author, post: apoc.map.merge(properties(post), {__typename: labels(post)[0], author: properties(postAuthor)})} AS finalResource', + labels(resource)[0] = "Report", ' + MATCH (reportedResource)<-[:BELONGS_TO]-(resource)<-[filed:FILED]-(user) + RETURN {__typename: "FiledReport", reportId: resource.id, createdAt: filed.createdAt, reasonCategory: filed.reasonCategory, reasonDescription: filed.reasonDescription, resource: apoc.map.merge(properties(reportedResource), {__typename: labels(reportedResource)[0]})} AS finalResource' + ], + '', + { + resource: resource, + user: user + }) YIELD value + RETURN notification {.*, from: value.finalResource, to: properties(user)} ${orderByClause} ${offset} ${limit} + + // Wolle + // the UNION ALL with ORDER BY and SKIP, LIMIT is possible since Neo4j 4.0. See https://neo4j.com/docs/cypher-manual/4.0/clauses/call-subquery/#subquery-post-union + // refactor the following to the new CALL {} subquery + // MATCH (author:User)-[:WROTE]->(post:Post)-[notification:NOTIFIED]->(user:User {id: $id}) + // WHERE NOT post.deleted AND NOT post.disabled + // ${whereClause} + // WITH user, notification, post {.*, __typename: labels(post)[0], author: properties(author)} + // RETURN notification {.*, from: post, to: properties(user)} + + // UNION ALL + // MATCH (author:User)-[:WROTE]->(comment:Comment)-[:COMMENTS]->(post:Post)<-[:WROTE]-(postAuthor:User), + // (comment)-[notification:NOTIFIED]->(user:User {id: $id}) + // WHERE NOT comment.deleted AND NOT comment.disabled + // ${whereClause} + // WITH user, notification, comment {.*, __typename: labels(comment)[0], author: properties(author), post: apoc.map.merge(properties(post), {__typename: labels(post)[0], author: properties(postAuthor)})} + // RETURN notification {.*, from: comment, to: properties(user)} + + // UNION ALL + // MATCH (reportedResource)<-[:BELONGS_TO]-(report)<-[file:FILED]-(user:User {id:$id}), + // (report:Report)-[notification:NOTIFIED]->(user) + // WHERE (reportedResource:User) OR (reportedResource:Post) OR (reportedResource:Comment) + // ${whereClause} + // // Wolle - Here the three different case are not distinguished and therefore Post is not added to Comment and the authors are not added etc. + // WITH + // user, + // notification, + // { + // __typename: "FiledReport", + // createdAt: file.createdAt, + // reasonCategory: file.reasonCategory, + // reasonDescription: file.reasonDescription, + // reportId: report.id, + // resource: apoc.map.merge(properties(reportedResource), { + // __typename: labels(reportedResource)[0] + // }) + // } AS filedReport + // RETURN notification {.*, from: filedReport, to: properties(user)} + // ${orderByClause} + // ${offset} ${limit} `, { id: currentUser.id }, ) log(notificationsTransactionResponse) - return notificationsTransactionResponse.records.map(record => record.get('notification')) + // Wolle return notificationsTransactionResponse.records.map(record => record.get('notification')) + const notification = notificationsTransactionResponse.records.map(record => record.get('notification')) + // Wolle console.log('notification: ', notification) + return notification }) try { const notifications = await readTxResultPromise diff --git a/backend/src/schema/resolvers/notifications.spec.js b/backend/src/schema/resolvers/notifications.spec.js index 7236a0972..bb086a501 100644 --- a/backend/src/schema/resolvers/notifications.spec.js +++ b/backend/src/schema/resolvers/notifications.spec.js @@ -230,26 +230,47 @@ describe('given some notifications', () => { ... on Comment { content } - ... on Report { - id - filed { - reasonCategory - reasonDescription - reportedResource { - __typename - ... on User { - id - name - } - ... on Post { - id - title - content - } - ... on Comment { - id - content - } + # Wolle ... on Report { + # id + # filed { + # reasonCategory + # reasonDescription + # reportedResource { + # __typename + # ... on User { + # id + # name + # } + # ... on Post { + # id + # title + # content + # } + # ... on Comment { + # id + # content + # } + # } + # } + # } + ... on FiledReport { + reportId + reasonCategory + reasonDescription + resource { + __typename + ... on User { + id + name + } + ... on Post { + id + title + content + } + ... on Comment { + id + content } } } @@ -280,21 +301,17 @@ describe('given some notifications', () => { read: true, reason: 'filed_report_on_resource', from: { - __typename: 'Report', - id: 'reportOnPost', - filed: [ - { - reasonCategory: 'other', - reasonDescription: - "This shouldn't be shown to anybody else! It's my private thing!", - reportedResource: { - __typename: 'Post', - id: 'p4', - title: 'Bad Post', - content: 'I am bad content !!!', - }, - }, - ], + __typename: 'FiledReport', + reportId: 'reportOnPost', + reasonCategory: 'other', + reasonDescription: + "This shouldn't be shown to anybody else! It's my private thing!", + resource: { + __typename: 'Post', + id: 'p4', + title: 'Bad Post', + content: 'I am bad content !!!', + }, }, }, { @@ -303,19 +320,15 @@ describe('given some notifications', () => { read: false, reason: 'filed_report_on_resource', from: { - __typename: 'Report', - id: 'reportOnUser', - filed: [ - { - reasonCategory: 'discrimination_etc', - reasonDescription: 'This user is harassing me with bigoted remarks!', - reportedResource: { - __typename: 'User', - id: 'badWomen', - name: 'Mrs. Badwomen', - }, - }, - ], + __typename: 'FiledReport', + reportId: 'reportOnUser', + reasonCategory: 'discrimination_etc', + reasonDescription: 'This user is harassing me with bigoted remarks!', + resource: { + __typename: 'User', + id: 'badWomen', + name: 'Mrs. Badwomen', + }, }, }, { @@ -324,20 +337,16 @@ describe('given some notifications', () => { read: false, reason: 'filed_report_on_resource', from: { - __typename: 'Report', - id: 'reportOnComment', - filed: [ - { - reasonCategory: 'discrimination_etc', - reasonDescription: 'This user is harassing me!', - reportedResource: { - __typename: 'Comment', - id: 'c4', - content: - 'I am harassing content in a harassing comment to a bad post !!!', - }, - }, - ], + __typename: 'FiledReport', + reportId: 'reportOnComment', + reasonCategory: 'discrimination_etc', + reasonDescription: 'This user is harassing me!', + resource: { + __typename: 'Comment', + id: 'c4', + content: + 'I am harassing content in a harassing comment to a bad post !!!', + }, }, }, expect.objectContaining({ @@ -398,19 +407,15 @@ describe('given some notifications', () => { read: false, reason: 'filed_report_on_resource', from: { - __typename: 'Report', - id: 'reportOnUser', - filed: [ - { - reasonCategory: 'discrimination_etc', - reasonDescription: 'This user is harassing me with bigoted remarks!', - reportedResource: { - __typename: 'User', - id: 'badWomen', - name: 'Mrs. Badwomen', - }, - }, - ], + __typename: 'FiledReport', + reportId: 'reportOnUser', + reasonCategory: 'discrimination_etc', + reasonDescription: 'This user is harassing me with bigoted remarks!', + resource: { + __typename: 'User', + id: 'badWomen', + name: 'Mrs. Badwomen', + }, }, }, { @@ -419,20 +424,16 @@ describe('given some notifications', () => { read: false, reason: 'filed_report_on_resource', from: { - __typename: 'Report', - id: 'reportOnComment', - filed: [ - { - reasonCategory: 'discrimination_etc', - reasonDescription: 'This user is harassing me!', - reportedResource: { - __typename: 'Comment', - id: 'c4', - content: - 'I am harassing content in a harassing comment to a bad post !!!', - }, - }, - ], + __typename: 'FiledReport', + reportId: 'reportOnComment', + reasonCategory: 'discrimination_etc', + reasonDescription: 'This user is harassing me!', + resource: { + __typename: 'Comment', + id: 'c4', + content: + 'I am harassing content in a harassing comment to a bad post !!!', + }, }, }, { @@ -648,8 +649,8 @@ describe('given some notifications', () => { createdAt: '2020-01-14T12:33:48.651Z', read: true, from: { - __typename: 'Report', - id: 'reportOnComment', + __typename: 'FiledReport', + reportId: 'reportOnComment', }, }, }, diff --git a/backend/src/schema/types/type/FILED.gql b/backend/src/schema/types/type/FILED.gql index 1de233465..adab1b14b 100644 --- a/backend/src/schema/types/type/FILED.gql +++ b/backend/src/schema/types/type/FILED.gql @@ -19,10 +19,10 @@ enum ReasonCategory { } type FiledReport { + reportId: ID! createdAt: String! reasonCategory: ReasonCategory! reasonDescription: String! - reportId: ID! resource: ReportedResource! } diff --git a/backend/src/schema/types/type/NOTIFIED.gql b/backend/src/schema/types/type/NOTIFIED.gql index 4b4b61c63..162e733ae 100644 --- a/backend/src/schema/types/type/NOTIFIED.gql +++ b/backend/src/schema/types/type/NOTIFIED.gql @@ -8,7 +8,8 @@ type NOTIFIED { to: User! } -union NotificationSource = Post | Comment | Report +# Wolle union NotificationSource = Post | Comment | Report +union NotificationSource = Post | Comment | FiledReport enum NotificationOrdering { createdAt_asc diff --git a/webapp/graphql/Moderation.js b/webapp/graphql/Moderation.js index f4796d080..23b955798 100644 --- a/webapp/graphql/Moderation.js +++ b/webapp/graphql/Moderation.js @@ -1,7 +1,6 @@ import gql from 'graphql-tag' export const reportsListQuery = () => { - // no limit for the moment like before: "reports(first: 20, orderBy: createdAt_desc)" return gql` query( $orderBy: ReportOrdering