Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions internal/db/posts/models/post.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package models

import "time"

// this struct will be used in internal packages
// for calling Post interface methods.
type Post struct {
Id string `bson:"_id,omitempty"`
UserId int `bson:"userId,omitempty"`
AuthorName string `bson:"authorName,omitempty"`
CreatedAt time.Time `bson:"createdAt,omitempty"`
CityId int `bson:"cityId,omitempty"`
CountryId int `bson:"countryId,omitempty"`
Coordinates Point `bson:"coordinates,omitempty"`
IsActive bool `bson:"isActive,omitempty"`
LikesCount int `bson:"likesCount,omitempty"`
CommentsCount int `bson:"commentsCount,omitempty"`
Content Content `bson:"content,omitempty,inline"`
}

type Point struct {
Type string `bson:"type"` //needs to be set to Point
Coordinates []float64 `bson:"coordinates"` //[long,lat]
}

type Content struct {
Text string `bson:"text,omitempty"`
BackgroundUrl string `bson:"backgroundUrl,omitempty"`
BackgroundType BackgroundType `bson:"backgroundType"`
}

type BackgroundType int

const (
PreloadedImage BackgroundType = iota
PreloadedVideo
CustomImage
CustomVideo
)
13 changes: 13 additions & 0 deletions internal/db/posts/posts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package posts

import (
"context"

"github.com/TheDevExperiment/server/internal/db/posts/models"
)

type Posts interface {
Create(context.Context, models.Post) error
FindNearby(context.Context, float64, float64) ([]models.Post, error)
Like(context.Context, string) error
}
96 changes: 96 additions & 0 deletions internal/db/posts/posts_repository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package posts

import (
"context"

"github.com/TheDevExperiment/server/internal/db"
"github.com/TheDevExperiment/server/internal/db/posts/models"
"github.com/TheDevExperiment/server/internal/log"
"github.com/spf13/viper"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)

type PostsRepository struct {
collection *mongo.Collection
}

var singletonPostCollection *mongo.Collection

const defaultNearbySearchRadius = 1000 // 1km
const defaultPageLimit = 10

func NewPostsRepository() *PostsRepository {
// use mongodb to find collection here
if singletonPostCollection == nil {
log.Debug("Created connection to post collection")
singletonPostCollection = db.GetCollection(viper.GetString("mongodb.db_name"), "posts")
}
return &PostsRepository{collection: singletonPostCollection}
}

func (pr *PostsRepository) Create(ctx context.Context, post models.Post) error {
log.Debugf("Received new post create request data: %+v", post)
res, err := pr.collection.InsertOne(ctx, post)
log.Debugf("Response received from mongo: %+v", res)
return err
}

func prepareNearbySortQuery(latitude, longitude float64) primitive.M {
query := bson.M{
"coordinates": bson.M{
"$near": bson.M{
"$geometry": bson.M{
"type": "Point",
"coordinates": []float64{longitude, latitude},
},
"$maxDistance": defaultNearbySearchRadius,
},
},
}
return query
}

func preparePaginatedNearbySortOpts(page int) *options.FindOptions {
findOptions := options.Find()
findOptions.SetLimit(int64(defaultPageLimit)) // Set the limit to the specified value
findOptions.SetSkip(int64((page - 1) * defaultPageLimit)) // Skip records based on the page number and limit
findOptions.SetSort(bson.D{{Key: "_id", Value: -1}}) // Sort by "_id" field in descending order
findOptions.SetProjection(bson.M{"coordinates": 0}) // Exclude "coordinates" field from the result
return findOptions
}

func (pr *PostsRepository) FindNearby(ctx context.Context, lat, long float64, page int) ([]models.Post, error) {
log.Debugf("Received new nearby req data: %f %f", lat, long)
query := prepareNearbySortQuery(lat, long)
optsWithPagination := preparePaginatedNearbySortOpts(page)

cur, err := pr.collection.Find(ctx, query, optsWithPagination)
if err != nil {
return nil, err
}
defer cur.Close(ctx)

var posts []models.Post
for cur.Next(ctx) {
var post models.Post
err := cur.Decode(&post)
if err != nil {
log.Errorf("Error while parsing doc: %s", err.Error())
continue
}
posts = append(posts, post)
}

if err := cur.Err(); err != nil {
return nil, err
}

return posts, nil
}

func (pr *PostsRepository) Like(context.Context, string) error {
return nil
}
54 changes: 54 additions & 0 deletions internal/post/post.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package post

import (
"net/http"

"github.com/TheDevExperiment/server/internal/db/posts"
"github.com/TheDevExperiment/server/router/models"
"github.com/gin-gonic/gin"
)

func CreateV1(c *gin.Context) {
// first bind the req to our model
var req models.CreatePostRequest
var res models.CreatePostResponse
pr := posts.NewPostsRepository()

if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

err := pr.Create(c, req.Post)
if err != nil {
httpCode := http.StatusInternalServerError
res.Message = err.Error()
c.JSON(httpCode, res)
return
}
res.Message = "Created new post"
c.JSON(http.StatusOK, res)
}

func NearbyV1(c *gin.Context) {
// first bind the req to our model
var req models.NearbyPostRequest
var res models.NearbyPostResponse
pr := posts.NewPostsRepository()

if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

posts, err := pr.FindNearby(c, req.Latitude, req.Longitude, req.Page)
if err != nil {
httpCode := http.StatusInternalServerError
res.Message = err.Error()
c.JSON(httpCode, res)
return
}

res.Posts = posts
c.JSON(http.StatusOK, res)
}
57 changes: 21 additions & 36 deletions mongo-seed/posts.json
Original file line number Diff line number Diff line change
@@ -1,41 +1,26 @@
[
{
"_id": {"$oid": "6170c708b210f8e6e31d6c94"},
"userId": {"$oid": "6170c6d9b210f8e6e31d6c91"},
"authorName": "John Doe",
"createdAt": {"$date": "2022-10-22T14:30:00.000Z"},
"content": {
"message": "hello world",
"fetchUrl": null,
"backgroundType": "Image"
},
"cityId": "New York",
"countryId": "USA",
"coordinate": {
{
"_id": "6061f072c1760a272b4bb49a",
"userId": 12345,
"authorName": "John Doe",
"createdAt": "2023-04-10T10:30:00Z",
"cityId": 1,
"countryId": 2,
"coordinates": {
"type": "Point",
"coordinates": [-73.935242, 40.730610]
},
"isActive": true,
"likes": 5
"coordinates": [
-122.4194,
37.7749
]
},
{
"_id": {"$oid": "6170c708b210f8e6e31d6c95"},
"userId": {"$oid": "6170c6d9b210f8e6e31d6c92"},
"authorName": "Jane Smith",
"createdAt": {"$date": "2022-10-23T16:30:00.000Z"},
"content": {
"message": "bye world",
"fetchUrl": null,
"backgroundType": "Image"
},
"cityId": "Toronto",
"countryId": "Canada",
"coordinate": {
"type": "Point",
"coordinates": [-79.3832, 43.6532]
},
"isActive": true,
"likes": 10
"isActive": true,
"likesCount": 10,
"commentsCount": 5,
"content": {
"text": "Lorem ipsum dolor sit amet",
"backgroundUrl": "https://example.com/image.jpg",
"backgroundType": 0
}
]
}
]

23 changes: 23 additions & 0 deletions router/models/post.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package models

import "github.com/TheDevExperiment/server/internal/db/posts/models"

type CreatePostRequest struct {
Post models.Post `json:"post" binding:"required"`
}

type CreatePostResponse struct {
Message string `form:"message" json:"message" binding:"required"`
}

type NearbyPostRequest struct {
Latitude float64 `json:"latitude" binding:"required"`
Longitude float64 `json:"longitude" binding:"required"`
Page int ` json:"page"`
// Radius int -> if app wants to support tweakable filter
}

type NearbyPostResponse struct {
Posts []models.Post `json:"posts" binding:"required"`
Message string
}
3 changes: 3 additions & 0 deletions router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package router
import (
"github.com/TheDevExperiment/server/internal/auth"
"github.com/TheDevExperiment/server/internal/db/repositories"
"github.com/TheDevExperiment/server/internal/post"
"github.com/gin-gonic/gin"
)

Expand All @@ -27,5 +28,7 @@ func SetupRouter() *gin.Engine {

// define all the routes
r.POST("/auth/v1/guest-validate", auth.GuestValidateV1)
r.POST("/post/v1/create", post.CreateV1)
r.POST("/post/v1/nearby", post.NearbyV1)
return r
}