將 MongoDB 與 Go 搭配使用

這部分 Go Bookshelf 教學課程說明範例應用程式如何將持續性資料儲存在 MongoDB 資料庫中。

本頁面是多頁教學課程的一部分。如要從頭開始並閱讀設定操作說明,請前往 Go Bookshelf 應用程式頁面。

在 Google Compute Engine 上執行 MongoDB

如果您尚未設定 Mongo 執行個體,可使用 GCP 上的 AtlasmLab,建立一個在 Google Cloud Platform 上執行的代管 Mongo 執行個體。如果您要使用在 Compute Engine 上執行的非代管 MongoDB 執行個體,請參閱 Bitnami 的預先設定的點擊部署解決方案

如要獲得最佳效能,請確保您的 MongoDB 執行個體由 Google Cloud Platform 託管,且位於與您的應用程式相同的地區中。

根據預設,MongoDB 會使用通訊埠 27017 進行通訊。設定 MongoDB 執行個體之後,您可能需要設定防火牆規則,以允許這個通訊埠傳輸流量。針對在 Google Cloud Platform 上執行的執行個體,請參閱使用防火牆規則以取得操作說明。

設定

  1. 前往包含程式碼範例的目錄:

    Linux/macOS

    cd $GOPATH/src/github.com/GoogleCloudPlatform/golang-samples/getting-started/bookshelf
    

    Windows

    cd %GOPATH%\src\github.com\GoogleCloudPlatform\golang-samples\getting-started\bookshelf
    

  2. 開啟 config.go 進行編輯。

  3. 將下面這兩行取消註解:

    // var cred *mgo.Credential
    // DB, err = newMongoDB("localhost", cred)
    
  4. localhost 替換為 MongoDB 執行個體的外部 IP 位址。這是您在之前區段中記下的外部 IP。您也可以透過執行 gcloud compute instances list 找到這個外部 IP 位址。

  5. 儲存並關閉 config.go

在本機電腦執行應用程式

  1. 執行應用程式以啟動本機網路伺服器:

    cd app
    go run app.go auth.go template.go
    
  2. 在網路瀏覽器中輸入此位址:

    http://localhost:8080

現在,您可以瀏覽應用程式的網頁,並新增、編輯與刪除書籍。

按下 Control+C 即可離開本機網路伺服器。

將應用程式部署至 App Engine 彈性環境

  1. app 目錄中,輸入下列指令以部署範例:

    gcloud app deploy
    
  2. 在網路瀏覽器中,輸入下列網址。將 [YOUR_PROJECT_ID] 替換為您的專案 ID:

    https://[YOUR_PROJECT_ID].appspot.com
    

如果您更新應用程式,可輸入與第一次部署應用程式時使用的相同指令部署更新版本。新部署會為您的應用程式建立新版本,並會將它升級為預設版本。 應用程式的較舊版本會保留下來,相關聯的 VM 執行個體也會保留下來。請注意,這些應用程式版本和 VM 執行個體全部都是計費資源。

您可以刪除應用程式的非預設版本來降低費用。

若要刪除應用程式版本:

  1. 前往 GCP 主控台的「App Engine Versions」(App Engine 版本) 頁面。

    前往版本頁面

  2. 找到您要刪除的非預設應用程式版本,然後點選旁邊的核取方塊。
  3. 按一下頁面頂部的 [刪除] 按鈕, 刪除應用程式版本。

如需有關清除計費資源的完整資訊,請參閱本教學課程最後一個步驟的清除一節。

應用程式結構

下圖顯示範例應用程式元件彼此連線的方式。

Bookshelf 應用程式部署程序與結構

瞭解程式碼

這部分內容會逐步引導您瞭解應用程式程式碼,並說明其運作方式。

透過表單處理使用者提交內容

當使用者按一下 [Add Book] (新增書籍) 時,瀏覽器會顯示 /books/add,且 addFormHandler 中的 app/app.go 函式會轉譯一個表單,使用者可在這個表單中新增書籍:

r.Methods("GET").Path("/books/add").
	Handler(appHandler(addFormHandler))
// addFormHandler displays a form that captures details of a new book to add to
// the database.
func addFormHandler(w http.ResponseWriter, r *http.Request) *appError {
	return editTmpl.Execute(w, r, nil)
}

新增/編輯表單的圖片

表單包含「Title」、「Author」、「Data Published」與「Description」的文字輸入欄位;也包含其他一些內容,用於教學課程的其他部分:

<form method="post" enctype="multipart/form-data" action="/books{{if .}}/{{.ID}}{{end}}">
  <div class="form-group">
    <label for="title">Title</label>
    <input class="form-control" name="title" id="title" value="{{.Title}}">
  </div>
  <div class="form-group">
    <label for="author">Author</label>
    <input class="form-control" name="author" id="author" value="{{.Author}}">
  </div>
  <div class="form-group">
    <label for="publishedDate">Date Published</label>
    <input class="form-control" name="publishedDate" id="publishedDate" value="{{.PublishedDate}}">
  </div>
  <div class="form-group">
    <label for="description">Description</label>
    <input class="form-control" name="description" id="description" value="{{.Description}}">
  </div>
  <div class="form-group">
    <label for="image">Cover Image</label>
    <input class="form-control" name="image" id="image" type="file">
  </div>
  <button class="btn btn-success">Save</button>
  <input type="hidden" name="imageURL" value="{{.ImageURL}}">
  <input type="hidden" name="createdBy" value="{{.CreatedBy}}">
  <input type="hidden" name="createdByID" value="{{.CreatedByID}}">
</form>

處理表單提交內容

當使用者填入表單並按一下 [Save] (儲存) 時,以下程式碼會處理表單的 HTTP POST /books 操作。程式碼會透過呼叫 bookshelf.DB.AddBook() 函式的方式,將新書籍插入資料庫中。

r.Methods("POST").Path("/books").
	Handler(appHandler(createHandler))
// createHandler adds a book to the database.
func createHandler(w http.ResponseWriter, r *http.Request) *appError {
	book, err := bookFromForm(r)
	if err != nil {
		return appErrorf(err, "could not parse book from form: %v", err)
	}
	id, err := bookshelf.DB.AddBook(book)
	if err != nil {
		return appErrorf(err, "could not save book: %v", err)
	}
	go publishUpdate(id)
	http.Redirect(w, r, fmt.Sprintf("/books/%d", id), http.StatusFound)
	return nil
}

db_mongo.go 中定義的 AddBook 函式可執行 Insert() 作業,將使用者提交的資料做為文件新增至 MongoDB 集合。

// AddBook saves a given book, assigning it a new ID.
func (db *mongoDB) AddBook(b *Book) (id int64, err error) {
	id, err = randomID()
	if err != nil {
		return 0, fmt.Errorf("mongodb: could not assign a new ID: %v", err)
	}

	b.ID = id
	if err := db.c.Insert(b); err != nil {
		return 0, fmt.Errorf("mongodb: could not add book: %v", err)
	}
	return id, nil
}

當使用者按一下 [Books] (書籍) 時,瀏覽器會顯示 /books 頁面,且 ListBooks 方法會顯示資料儲存庫中的所有書籍。

陳述式 db.c.Find(nil) 會建立一項查詢,這項查詢會選取集合中的所有文件。這項查詢包含 .Sort("title"),用於指定根據書名按照字母排列結果順序。

呼叫 All 即可執行該查詢,進而將所有傳回的文件附加至 result 部分。

// ListBooks returns a list of books, ordered by title.
func (db *mongoDB) ListBooks() ([]*Book, error) {
	var result []*Book
	if err := db.c.Find(nil).Sort("title").All(&result); err != nil {
		return nil, err
	}
	return result, nil
}
本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁