hello_mongo.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. package main
  2. import (
  3. "encoding/json"
  4. "html/template"
  5. "log"
  6. "math/rand"
  7. "net/http"
  8. "sort"
  9. "strconv"
  10. "gopkg.in/mgo.v2"
  11. "gopkg.in/mgo.v2/bson"
  12. )
  13. const (
  14. connectionString = "localhost"
  15. worldRowCount = 10000
  16. fortuneHTML = `<!DOCTYPE html>
  17. <html>
  18. <head>
  19. <title>Fortunes</title>
  20. </head>
  21. <body>
  22. <table>
  23. <tr>
  24. <th>id</th>
  25. <th>message</th>
  26. </tr>
  27. {{range .}}
  28. <tr>
  29. <td>{{.Id}}</td>
  30. <td>{{.Message}}</td>
  31. </tr>
  32. {{end}}
  33. </table>
  34. </body>
  35. </html>`
  36. )
  37. var (
  38. tmpl = template.Must(template.New("fortune.html").Parse(fortuneHTML))
  39. database *mgo.Database
  40. fortunes *mgo.Collection
  41. worlds *mgo.Collection
  42. )
  43. type Message struct {
  44. Message string `json:"message"`
  45. }
  46. type World struct {
  47. Id uint16 `bson:"_id" json:"id"`
  48. RandomNumber uint16 `bson:"randomNumber" json:"randomNumber"`
  49. }
  50. type Fortune struct {
  51. Id uint16 `bson:"_id" json:"id"`
  52. Message string `bson:"message" json:"message"`
  53. }
  54. type Fortunes []Fortune
  55. func (s Fortunes) Len() int {
  56. return len(s)
  57. }
  58. func (s Fortunes) Swap(i, j int) {
  59. s[i], s[j] = s[j], s[i]
  60. }
  61. type ByMessage struct{ Fortunes }
  62. func (s ByMessage) Less(i, j int) bool {
  63. return s.Fortunes[i].Message < s.Fortunes[j].Message
  64. }
  65. func main() {
  66. session, err := mgo.Dial(connectionString)
  67. if err != nil {
  68. log.Fatalf("Error opening database: %v", err)
  69. }
  70. defer session.Close()
  71. database = session.DB("hello_world")
  72. worlds = database.C("world")
  73. fortunes = database.C("fortune")
  74. http.HandleFunc("/db", dbHandler)
  75. http.HandleFunc("/fortune", fortuneHandler)
  76. http.HandleFunc("/queries", queriesHandler)
  77. http.HandleFunc("/update", updateHandler)
  78. http.ListenAndServe(":8080", nil)
  79. }
  80. // Helper for random numbers
  81. func getRandomNumber() uint16 {
  82. return uint16(rand.Intn(worldRowCount) + 1)
  83. }
  84. // Test 2: Single database query
  85. func dbHandler(w http.ResponseWriter, r *http.Request) {
  86. var world World
  87. query := bson.M{"_id": getRandomNumber()}
  88. if err := worlds.Find(query).One(&world); err != nil {
  89. log.Fatalf("Error finding world with id: %s", err.Error())
  90. }
  91. w.Header().Set("Content-Type", "application/json")
  92. w.Header().Set("Server", "go-mongodb")
  93. json.NewEncoder(w).Encode(&world)
  94. }
  95. // Helper for getting the "queries" parameter
  96. func getQueriesParam(r *http.Request) int {
  97. n := 1
  98. if nStr := r.URL.Query().Get("queries"); len(nStr) > 0 {
  99. n, _ = strconv.Atoi(nStr)
  100. }
  101. if n < 1 {
  102. n = 1
  103. } else if n > 500 {
  104. n = 500
  105. }
  106. return n
  107. }
  108. // Test 3: Multiple database queries
  109. func queriesHandler(w http.ResponseWriter, r *http.Request) {
  110. n := getQueriesParam(r)
  111. world := make([]World, n)
  112. for i := 0; i < n; i++ {
  113. query := bson.M{"_id": getRandomNumber()}
  114. if err := worlds.Find(query).One(&world[i]); err != nil {
  115. log.Fatalf("Error finding world with id: %s", err.Error())
  116. }
  117. }
  118. w.Header().Set("Content-Type", "application/json")
  119. w.Header().Set("Server", "go-mongodb")
  120. json.NewEncoder(w).Encode(world)
  121. }
  122. // Test 4: Fortunes
  123. func fortuneHandler(w http.ResponseWriter, r *http.Request) {
  124. w.Header().Set("Content-Type", "text/html; charset=utf-8")
  125. w.Header().Set("Server", "go-mongodb")
  126. f := make(Fortunes, 16)
  127. if err := fortunes.Find(nil).All(&f); err == nil {
  128. f = append(f, Fortune{Message: "Additional fortune added at request time."})
  129. sort.Sort(ByMessage{f})
  130. if err := tmpl.Execute(w, f); err != nil {
  131. http.Error(w, err.Error(), http.StatusInternalServerError)
  132. }
  133. } else {
  134. http.Error(w, err.Error(), http.StatusInternalServerError)
  135. }
  136. }
  137. // Test 5: Database updates
  138. func updateHandler(w http.ResponseWriter, r *http.Request) {
  139. n := getQueriesParam(r)
  140. world := make([]World, n)
  141. for i := 0; i < n; i++ {
  142. query := bson.M{"_id": getRandomNumber()}
  143. if err := worlds.Find(query).One(&world[i]); err != nil {
  144. log.Fatalf("Error finding world with id: %s", err.Error())
  145. }
  146. world[i].RandomNumber = getRandomNumber()
  147. update := bson.M{"$set": bson.M{"randomNumber": world[i].RandomNumber}}
  148. if err := worlds.Update(query, update); err != nil {
  149. log.Fatalf("Error updating world with id: %s", err.Error())
  150. }
  151. }
  152. w.Header().Set("Content-Type", "application/json")
  153. w.Header().Set("Server", "Go")
  154. json.NewEncoder(w).Encode(&world)
  155. }