Skip to content

Commit 696408b

Browse files
committed
getcontestquestionbyid - mongo aggregation
1 parent 22b5677 commit 696408b

File tree

5 files changed

+93
-4
lines changed

5 files changed

+93
-4
lines changed

cmd/portal-api/main.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,7 @@ router.Handle("GET /api/admin/test",
7575
router.HandleFunc("POST /api/testcase",testcase.CreateTestCase(storage))
7676
router.HandleFunc("GET /api/contest",contest.GetAllContests(storage))
7777
router.HandleFunc("GET /api/contest/{id}",contest.GetContestById(storage))
78-
// router.HandleFunc("GET /api/users/{id}",users.GetById(storage))
79-
// router.HandleFunc("GET /api/users",users.GetAll(storage))
78+
router.HandleFunc("GET /api/question/{id}",question.GetQuestionById(storage))
8079

8180
//start server
8281

pkg/http/handler/question/question.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ package question
22

33
import (
44
"encoding/json"
5+
"fmt"
56
"net/http"
6-
7+
"strings"
78
"github.com/krishkumar84/bdcoe-golang-portal/pkg/storage"
89
"github.com/krishkumar84/bdcoe-golang-portal/pkg/types"
910
"github.com/krishkumar84/bdcoe-golang-portal/pkg/utils/response"
@@ -25,4 +26,23 @@ func CreateQuestion(storage storage.Storage) http.HandlerFunc {
2526

2627
response.WriteJson(w, http.StatusCreated, map[string]string{"question_id": questionId})
2728
}
29+
}
30+
31+
func GetQuestionById(storage storage.Storage) http.HandlerFunc {
32+
return func(w http.ResponseWriter, r *http.Request) {
33+
path := r.URL.Path
34+
id := path[strings.LastIndex(path, "/")+1:]
35+
36+
if id == "" {
37+
response.WriteJson(w, http.StatusBadRequest, response.GeneralError(fmt.Errorf("contest id is required")))
38+
return
39+
}
40+
fmt.Println("Question ID: ", id)
41+
question, err := storage.GetQuestionById(id)
42+
if err != nil {
43+
response.WriteJson(w, http.StatusInternalServerError, response.GeneralError(err))
44+
return
45+
}
46+
response.WriteJson(w, http.StatusOK, question)
47+
}
2848
}

pkg/storage/mongodb/mongodb.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,5 +237,74 @@ func (m *MongoDB) GetContestById(id string) ([]bson.M, error) {
237237
return nil, mongo.ErrNoDocuments
238238
}
239239

240+
return results, nil
241+
}
242+
243+
func (m *MongoDB) GetQuestionById(id string) ([]bson.M, error) {
244+
collection := m.db.Collection("questions")
245+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
246+
defer cancel()
247+
248+
objectId, err := primitive.ObjectIDFromHex(id)
249+
if err != nil {
250+
return nil, fmt.Errorf("invalid question id format")
251+
}
252+
253+
pipeline := mongo.Pipeline{
254+
{{Key: "$match", Value: bson.D{{Key: "_id", Value: objectId}}}},
255+
{{Key: "$addFields", Value: bson.D{
256+
{Key: "test_case_ids", Value: bson.D{
257+
{Key: "$map", Value: bson.D{
258+
{Key: "input", Value: "$test_case_ids"},
259+
{Key: "as", Value: "tid"},
260+
{Key: "in", Value: bson.D{
261+
{Key: "$toObjectId", Value: "$$tid"},
262+
}},
263+
}},
264+
}},
265+
}}},
266+
{{Key: "$lookup", Value: bson.D{
267+
{Key: "from", Value: "test_cases"},
268+
{Key: "localField", Value: "test_case_ids"},
269+
{Key: "foreignField", Value: "_id"},
270+
{Key: "as", Value: "test_cases"},
271+
}}},
272+
{{Key: "$project", Value: bson.D{
273+
{Key: "_id", Value: 1},
274+
{Key: "title", Value: 1},
275+
{Key: "description", Value: 1},
276+
{Key: "difficulty", Value: 1},
277+
{Key: "tags", Value: 1},
278+
{Key: "points", Value: 1},
279+
{Key: "test_cases", Value: bson.D{
280+
{Key: "$map", Value: bson.D{
281+
{Key: "input", Value: "$test_cases"},
282+
{Key: "as", Value: "tc"},
283+
{Key: "in", Value: bson.D{
284+
{Key: "_id", Value: "$$tc._id"},
285+
{Key: "input", Value: "$$tc.input"},
286+
{Key: "expected_output", Value: "$$tc.expected_output"},
287+
{Key: "visibility", Value: "$$tc.visibility"},
288+
}},
289+
}},
290+
}},
291+
}}},
292+
}
293+
294+
var results []bson.M
295+
cursor, err := collection.Aggregate(ctx, pipeline)
296+
if err != nil {
297+
return nil, fmt.Errorf("error executing aggregation: %v", err)
298+
}
299+
defer cursor.Close(ctx)
300+
301+
if err := cursor.All(ctx, &results); err != nil {
302+
return nil, fmt.Errorf("error decoding result: %v", err)
303+
}
304+
305+
if len(results) == 0 {
306+
return nil, mongo.ErrNoDocuments
307+
}
308+
240309
return results, nil
241310
}

pkg/storage/storage.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ type Storage interface {
1616
CreateTestCase(testCase types.TestCase) (string, error)
1717
GetAllContests() ([]types.ContestBasicInfo, error)
1818
GetContestById(id string) ([]bson.M, error)
19+
GetQuestionById(id string) ([]bson.M, error)
1920
}

pkg/types/models.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type Contest struct {
3333
}
3434

3535
type Question struct {
36-
ID string `bson:"_id,omitempty" json:"question_id" validate:"required"`
36+
ID string `bson:"_id,omitempty" json:"question_id"`
3737
Title string `bson:"title" json:"title" validate:"required"`
3838
Description string `bson:"description" json:"description" validate:"required"`
3939
Difficulty string `bson:"difficulty" json:"difficulty"`

0 commit comments

Comments
 (0)