From 302b4b5f9cedb7f5201873a4648a45f4d88118f1 Mon Sep 17 00:00:00 2001 From: SoXX Date: Fri, 10 May 2024 10:57:51 +0200 Subject: [PATCH 1/4] feat: added GetUserFavoritePostsWithPagination function --- internal/user.go | 49 ++++++++++++++++++++++++++++++++++++++++++++++ pkg/graph/graph.go | 3 +++ pkg/graph/impl.go | 4 ++++ 3 files changed, 56 insertions(+) diff --git a/internal/user.go b/internal/user.go index 89c9aa2..377efcf 100644 --- a/internal/user.go +++ b/internal/user.go @@ -315,3 +315,52 @@ func GetAllAnthroveUserIDs(ctx context.Context, driver neo4j.DriverWithContext) return anthroveUsers, nil } + +func GetUserFavoriteNodeWithPagination(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID, skip int, limit int) ([]models.AnthrovePost, error) { + var err error + var anthrovePosts []models.AnthrovePost + + query := ` + MATCH (user:User{user_id: $anthrove_user_id})-[r:FAV]->(p:AnthrovePost) + RETURN p as anthrovePost + ORDER BY id(r) DESC + SKIP $skip + LIMIT $limit; + ` + params := map[string]any{ + "anthrove_user_id": anthroveUserID, + "limit": limit, + "skip": skip, + } + + result, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) + if err != nil { + return nil, err + } + + if len(result.Records) == 0 { + return nil, nil + } + + for i := range result.Records { + record := result.Records[i] + + post, _, err := neo4j.GetRecordValue[neo4j.Node](record, "anthrovePost") + if err != nil { + return nil, err + } + + anthrovePosts = append(anthrovePosts, models.AnthrovePost{ + PostID: models.AnthrovePostID(post.Props["post_id"].(string)), + Rating: models.AnthroveRating(post.Props["rating"].(string)), + }) + + } + + log.WithFields(log.Fields{ + "anthrove_user_fav_count": len(anthrovePosts), + }).Trace("graph: got al anthrove user favorites") + + return anthrovePosts, nil + +} diff --git a/pkg/graph/graph.go b/pkg/graph/graph.go index 140b8cd..17666cb 100644 --- a/pkg/graph/graph.go +++ b/pkg/graph/graph.go @@ -97,4 +97,7 @@ type OtterSpace interface { // GetAllAnthroveUserIDs retrieves all user IDs from the OtterSpace graph. // It returns a slice of user IDs and an error if the operation fails. GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) + + //TODO + GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) ([]models.AnthrovePost, error) } diff --git a/pkg/graph/impl.go b/pkg/graph/impl.go index ca5fd15..3522a7e 100644 --- a/pkg/graph/impl.go +++ b/pkg/graph/impl.go @@ -96,6 +96,10 @@ func (g *graphConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]models.A return internal.GetAllAnthroveUserIDs(ctx, g.driver) } +func (g *graphConnection) GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) ([]models.AnthrovePost, error) { + return internal.GetUserFavoriteNodeWithPagination(ctx, g.driver, anthroveUserID, skip, limit) +} + func logger(graphDebug bool) func(config *config.Config) { return func(config *config.Config) { config.Log = internal.NewGraphLogger(graphDebug) From 7487ba3ffeef16c227cda43ad6cef673472addf9 Mon Sep 17 00:00:00 2001 From: SoXX Date: Wed, 15 May 2024 11:17:27 +0200 Subject: [PATCH 2/4] fix: ignore main.go files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 83411c1..9adc1a5 100644 --- a/.gitignore +++ b/.gitignore @@ -192,3 +192,4 @@ $RECYCLE.BIN/ .env +main.go From afaf112c5df69bccb7516a2c7d8eb3297f9ffa46 Mon Sep 17 00:00:00 2001 From: SoXX Date: Wed, 15 May 2024 11:18:01 +0200 Subject: [PATCH 3/4] feat: added GetUserFavoritePostsWithPagination --- internal/user.go | 63 ++++++++++++++++++++++++++++++++++++---------- pkg/graph/graph.go | 7 +++--- pkg/graph/impl.go | 2 +- 3 files changed, 55 insertions(+), 17 deletions(-) diff --git a/internal/user.go b/internal/user.go index 377efcf..d4f97c2 100644 --- a/internal/user.go +++ b/internal/user.go @@ -3,6 +3,7 @@ package internal import ( "context" "fmt" + "git.dragse.it/anthrove/otter-space-sdk/internal/utils" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "github.com/neo4j/neo4j-go-driver/v5/neo4j" @@ -316,16 +317,22 @@ func GetAllAnthroveUserIDs(ctx context.Context, driver neo4j.DriverWithContext) } -func GetUserFavoriteNodeWithPagination(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID, skip int, limit int) ([]models.AnthrovePost, error) { +func GetUserFavoriteNodeWithPagination(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { var err error - var anthrovePosts []models.AnthrovePost + var favoritePosts []models.FavoritePost query := ` - MATCH (user:User{user_id: $anthrove_user_id})-[r:FAV]->(p:AnthrovePost) - RETURN p as anthrovePost - ORDER BY id(r) DESC + CALL { + MATCH (user:User{user_id: $anthrove_user_id})-[r:FAV]->(p:AnthrovePost) + RETURN p.post_id AS post_id + ORDER BY id(p) ASC SKIP $skip - LIMIT $limit; + LIMIT $limit + } + WITH collect(post_id) AS faves + MATCH (a:AnthrovePost)<-[r:REFERENCE]-(s:Source) + WHERE a.post_id in faves + RETURN a AS anthrovePost, r AS postRelation, s AS Source ` params := map[string]any{ "anthrove_user_id": anthroveUserID, @@ -345,22 +352,52 @@ func GetUserFavoriteNodeWithPagination(ctx context.Context, driver neo4j.DriverW for i := range result.Records { record := result.Records[i] - post, _, err := neo4j.GetRecordValue[neo4j.Node](record, "anthrovePost") + anthrovePost, _, err := neo4j.GetRecordValue[neo4j.Node](record, "anthrovePost") if err != nil { return nil, err } - anthrovePosts = append(anthrovePosts, models.AnthrovePost{ - PostID: models.AnthrovePostID(post.Props["post_id"].(string)), - Rating: models.AnthroveRating(post.Props["rating"].(string)), - }) + postRelation, _, err := neo4j.GetRecordValue[neo4j.Relationship](record, "postRelation") + if err != nil { + return nil, err + } + + source, _, err := neo4j.GetRecordValue[neo4j.Node](record, "Source") + if err != nil { + return nil, err + } + + if len(favoritePosts) != 0 && favoritePosts[len(favoritePosts)-1].AnthrovePost.PostID == models.AnthrovePostID(anthrovePost.Props["post_id"].(string)) { + favoritePosts[len(favoritePosts)-1].Relations = append(favoritePosts[len(favoritePosts)-1].Relations, models.FavoriteRelations{ + SourcesID: source.Props["display_name"].(string), + Relations: models.AnthrovePostRelationship{ + PostID: postRelation.Props["source_post_id"].(string), + Url: postRelation.Props["url"].(string), + }, + }) + } else { + favoritePosts = append(favoritePosts, models.FavoritePost{ + AnthrovePost: models.AnthrovePost{ + PostID: models.AnthrovePostID(anthrovePost.Props["post_id"].(string)), + Rating: models.AnthroveRating(anthrovePost.Props["rating"].(string)), + }, + Relations: []models.FavoriteRelations{{ + SourcesID: source.Props["display_name"].(string), + Relations: models.AnthrovePostRelationship{ + PostID: postRelation.Props["source_post_id"].(string), + Url: postRelation.Props["url"].(string), + }, + }}, + }) + + } } log.WithFields(log.Fields{ - "anthrove_user_fav_count": len(anthrovePosts), + "anthrove_user_fav_count": len(favoritePosts), }).Trace("graph: got al anthrove user favorites") - return anthrovePosts, nil + return &models.FavoriteList{Posts: favoritePosts}, nil } diff --git a/pkg/graph/graph.go b/pkg/graph/graph.go index 17666cb..a824319 100644 --- a/pkg/graph/graph.go +++ b/pkg/graph/graph.go @@ -27,6 +27,7 @@ package graph import ( "context" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" ) @@ -86,7 +87,7 @@ type OtterSpace interface { // It returns a map of source domains to user-source relationships, and an error if the operation fails. GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.AnthroveUserRelationship, error) - // GetUserSourceLinks retrieves the links between a user and sources in the OtterSpace graph. + // GetSpecifiedUserSourceLink GetUserSourceLinks retrieves the links between a user and a specific source in the OtterSpace graph. // It returns a map of source domains to user-source relationships, and an error if the operation fails. GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.AnthroveUserRelationship, error) @@ -98,6 +99,6 @@ type OtterSpace interface { // It returns a slice of user IDs and an error if the operation fails. GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) - //TODO - GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) ([]models.AnthrovePost, error) + // GetUserFavoritePostsWithPagination gets all user favorites with relation and sources for the given user + GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) } diff --git a/pkg/graph/impl.go b/pkg/graph/impl.go index 3522a7e..4db1b3f 100644 --- a/pkg/graph/impl.go +++ b/pkg/graph/impl.go @@ -96,7 +96,7 @@ func (g *graphConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]models.A return internal.GetAllAnthroveUserIDs(ctx, g.driver) } -func (g *graphConnection) GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) ([]models.AnthrovePost, error) { +func (g *graphConnection) GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { return internal.GetUserFavoriteNodeWithPagination(ctx, g.driver, anthroveUserID, skip, limit) } From 5fb2a1770a8eb3981bba0885ae3c372d42404b7c Mon Sep 17 00:00:00 2001 From: SoXX Date: Wed, 15 May 2024 11:18:10 +0200 Subject: [PATCH 4/4] feat: added GetUserFavoritePostsWithPagination --- pkg/models/api.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 pkg/models/api.go diff --git a/pkg/models/api.go b/pkg/models/api.go new file mode 100644 index 0000000..0c2da29 --- /dev/null +++ b/pkg/models/api.go @@ -0,0 +1,15 @@ +package models + +type FavoriteRelations struct { + SourcesID string `json:"sources_id"` + Relations AnthrovePostRelationship `json:"relations"` +} + +type FavoritePost struct { + AnthrovePost AnthrovePost `json:"anthrove_post"` + Relations []FavoriteRelations `json:"relations"` +} + +type FavoriteList struct { + Posts []FavoritePost `json:"posts,omitempty"` +}