Skip to content

Commit 22b5677

Browse files
committed
getcontestwithquestionbyid- mongo aggregation
1 parent 7a8dfce commit 22b5677

File tree

6 files changed

+111
-12
lines changed

6 files changed

+111
-12
lines changed

cmd/portal-api/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ router.Handle("GET /api/admin/test",
7474
router.HandleFunc("POST /api/question",question.CreateQuestion(storage))
7575
router.HandleFunc("POST /api/testcase",testcase.CreateTestCase(storage))
7676
router.HandleFunc("GET /api/contest",contest.GetAllContests(storage))
77+
router.HandleFunc("GET /api/contest/{id}",contest.GetContestById(storage))
7778
// router.HandleFunc("GET /api/users/{id}",users.GetById(storage))
7879
// router.HandleFunc("GET /api/users",users.GetAll(storage))
7980

pkg/http/handler/contest/contest.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ package contest
22

33
import (
44
"encoding/json"
5+
"fmt"
56
"net/http"
7+
"strings"
68

79
"github.com/krishkumar84/bdcoe-golang-portal/pkg/storage"
810
"github.com/krishkumar84/bdcoe-golang-portal/pkg/types"
911
"github.com/krishkumar84/bdcoe-golang-portal/pkg/utils/response"
12+
"go.mongodb.org/mongo-driver/mongo"
1013
)
1114

1215
func CreateContest(storage storage.Storage) http.HandlerFunc {
@@ -37,4 +40,27 @@ func GetAllContests(storage storage.Storage) http.HandlerFunc {
3740

3841
response.WriteJson(w, http.StatusOK, contests)
3942
}
43+
}
44+
45+
func GetContestById(storage storage.Storage) http.HandlerFunc {
46+
return func(w http.ResponseWriter, r *http.Request) {
47+
path := r.URL.Path
48+
id := path[strings.LastIndex(path, "/")+1:]
49+
50+
if id == "" {
51+
response.WriteJson(w, http.StatusBadRequest, response.GeneralError(fmt.Errorf("contest id is required")))
52+
return
53+
}
54+
55+
contest, err := storage.GetContestById(id)
56+
if err != nil {
57+
if err == mongo.ErrNoDocuments {
58+
response.WriteJson(w, http.StatusNotFound, response.GeneralError(fmt.Errorf("contest not found")))
59+
return
60+
}
61+
response.WriteJson(w, http.StatusInternalServerError, response.GeneralError(err))
62+
return
63+
}
64+
response.WriteJson(w, http.StatusOK, contest)
65+
}
4066
}

pkg/storage/mongodb/mongodb.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,4 +174,68 @@ func (m *MongoDB) GetAllContests() ([]types.ContestBasicInfo, error) {
174174
}
175175

176176
return contests, nil
177+
}
178+
179+
func (m *MongoDB) GetContestById(id string) ([]bson.M, error) {
180+
objectId, err := primitive.ObjectIDFromHex(id)
181+
if err != nil {
182+
return nil, fmt.Errorf("invalid contest id format")
183+
}
184+
185+
pipeline := mongo.Pipeline{
186+
{{Key: "$match", Value: bson.D{{Key: "_id", Value: objectId}}}},
187+
{{Key: "$addFields", Value: bson.D{
188+
{Key: "question_ids", Value: bson.D{
189+
{Key: "$map", Value: bson.D{
190+
{Key: "input", Value: "$question_ids"},
191+
{Key: "as", Value: "qid"},
192+
{Key: "in", Value: bson.D{
193+
{Key: "$toObjectId", Value: "$$qid"},
194+
}},
195+
}},
196+
}},
197+
}}},
198+
{{Key: "$lookup", Value: bson.D{
199+
{Key: "from", Value: "questions"},
200+
{Key: "localField", Value: "question_ids"},
201+
{Key: "foreignField", Value: "_id"},
202+
{Key: "as", Value: "questions"},
203+
}}},
204+
{{Key: "$project", Value: bson.D{
205+
{Key: "_id", Value: "$_id"},
206+
{Key: "title", Value: "$title"},
207+
{Key: "start_time", Value: "$start_time"},
208+
{Key: "end_time", Value: "$end_time"},
209+
{Key: "description", Value: "$description"},
210+
{Key: "questions", Value: bson.D{
211+
{Key: "$map", Value: bson.D{
212+
{Key: "input", Value: "$questions"},
213+
{Key: "as", Value: "q"},
214+
{Key: "in", Value: bson.D{
215+
{Key: "_id", Value: "$$q._id"},
216+
{Key: "title", Value: "$$q.title"},
217+
{Key: "description", Value: "$$q.description"},
218+
{Key: "difficulty", Value: "$$q.difficulty"},
219+
}},
220+
}},
221+
}},
222+
}}},
223+
}
224+
225+
var results []bson.M
226+
cursor, err := m.db.Collection("contests").Aggregate(context.Background(), pipeline)
227+
if err != nil {
228+
return nil, fmt.Errorf("error executing aggregation: %v", err)
229+
}
230+
defer cursor.Close(context.Background())
231+
232+
if err := cursor.All(context.Background(), &results); err != nil {
233+
return nil, fmt.Errorf("error decoding result: %v", err)
234+
}
235+
236+
if len(results) == 0 {
237+
return nil, mongo.ErrNoDocuments
238+
}
239+
240+
return results, nil
177241
}

pkg/storage/storage.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package storage
2-
import "github.com/krishkumar84/bdcoe-golang-portal/pkg/types"
2+
import (
3+
"github.com/krishkumar84/bdcoe-golang-portal/pkg/types"
4+
"go.mongodb.org/mongo-driver/bson"
5+
)
36

47

58
type Storage interface {
@@ -12,4 +15,5 @@ type Storage interface {
1215
CreateQuestion(question types.Question) (string, error)
1316
CreateTestCase(testCase types.TestCase) (string, error)
1417
GetAllContests() ([]types.ContestBasicInfo, error)
15-
}
18+
GetContestById(id string) ([]bson.M, error)
19+
}

pkg/types/models.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ type User struct {
2222
}
2323

2424
type Contest struct {
25-
ID string `bson:"_id,omitempty" json:"contest_id"`
26-
Title string `bson:"title" json:"title" validate:"required"`
27-
StartTime time.Time `bson:"start_time" json:"start_time" validate:"required"`
28-
EndTime time.Time `bson:"end_time" json:"end_time" validate:"required"`
29-
Description string `bson:"description" json:"description" validate:"required"`
30-
CreatedBy primitive.ObjectID `bson:"created_by" json:"created_by"`
31-
QuestionIDs []string `bson:"question_ids" json:"question_ids" validate:"required"`
32-
CreatedAt time.Time `bson:"created_at" json:"created_at"`
25+
ID primitive.ObjectID `bson:"_id,omitempty" json:"contest_id"`
26+
Title string `bson:"title" json:"title" validate:"required"`
27+
StartTime time.Time `bson:"start_time" json:"start_time" validate:"required"`
28+
EndTime time.Time `bson:"end_time" json:"end_time" validate:"required"`
29+
Description string `bson:"description" json:"description" validate:"required"`
30+
CreatedBy string `bson:"created_by" json:"created_by"`
31+
QuestionIDs []string `bson:"question_ids" json:"question_ids" validate:"required"`
32+
CreatedAt time.Time `bson:"created_at" json:"created_at"`
3333
}
3434

3535
type Question struct {

pkg/types/types.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package types
22

3-
import "time"
3+
import (
4+
"time"
5+
)
6+
47
type ContestBasicInfo struct {
58
ID string `bson:"_id" json:"contest_id"`
69
Title string `bson:"title" json:"title"`
710
StartTime time.Time `bson:"start_time" json:"start_time"`
811
EndTime time.Time `bson:"end_time" json:"end_time"`
912
Description string `bson:"description" json:"description"`
10-
}
13+
}
14+

0 commit comments

Comments
 (0)