29

私は現在、Webアプリケーションにmgo libを備えたmongodbを使用していますが、使用方法が良いかどうかはわかりません..

package db

import (
    "gopkg.in/mgo.v2"
)

const (
    MongoServerAddr = "192.168.0.104"
    RedisServerAddr = "192.168.0.104"
)

var (
    MongoSession, err = mgo.Dial(MongoServerAddr)

    MDB  = MongoSession.DB("message")
    MCol = MDB.C("new")
    MSav = MDB.C("save")

    UDB  = MongoSession.DB("account")
    UCol = UDB.C("user")
)

データベース セッションを開始し、コレクションとドキュメントの値を取得する変数を作成します。そのため、コレクションをクエリする必要がある場合は、変数を使用して作成します。

そのように:

func UserExist(username string) bool {
    user := Users{}
    err := db.UCol.Find(bson.M{"username": username}).One(&user)
    if err != nil {
        return false
    } else {
        return true
    }
}

ベストプラクティスはありますか、それともこれで問題ありませんか..? ありがとう

4

3 に答える 3

65

そのようなグローバルセッションを使用しないことをお勧めします。代わりに、すべてのデータベース対話を担当する型を作成できます。例えば:

type DataStore struct {
    session *mgo.Session
}

func (ds *DataStore) ucol() *mgo.Collection { ... }

func (ds *DataStore) UserExist(user string) bool { ... }

その設計には多くの利点があります。重要なのは、同時に複数のセッションを実行できることです。たとえば、http ハンドラーがある場合は、その 1 つの要求のためだけに独立したセッションによってサポートされるローカル セッションを作成できます。

func (s *WebSite) dataStore() *DataStore {
    return &DataStore{s.session.Copy()}
}    

func (s *WebSite) HandleRequest(...) {
    ds := s.dataStore()
    defer ds.Close()
    ...
}

その場合、セッションは内部的にキャッシュされ、再利用/維持されるため、mgo ドライバーは適切に動作します。各セッションは、使用中に独立したソケットによってバックアップされ、独立した設定が構成されている場合があり、独立したエラー処理も行われます。これらは、単一のグローバル セッションを使用している場合に最終的に対処しなければならない問題です。

于 2014-10-26T18:45:42.897 に答える
2

あなたの質問に直接答えることはありませんが、mgo セッション チェックに関しては、mgo 呼び出し (mgo.session.Ping でさえも) パニックになるため、defer/recover を使用する必要があります。私が知る限り、mgo セッション状態 ( mgo godocs ) をチェックする他の方法はありません。Gustavo Niemeyerの提案を使用して、型にメソッドを追加できますDataStore

func (d *DataStore) EnsureConnected() {
    defer func() {
        if r := recover(); r != nil {
            //Your reconnect logic here.
        }
    }()

    //Ping panics if session is closed. (see mgo.Session.Panic())  
    d.Ping()
}
于 2016-11-02T17:31:10.473 に答える
0

go 1.7 では、Web サーバーで mongo セッションを処理する最も慣用的な方法は、新しい標準ライブラリ パッケージを使用して、リクエスト コンテキスト Done() が呼び出されるたびにcontext接続できるミドルウェアを作成することです。defer session.Close()したがって、閉じることを覚える必要はありません

AttachDeviceCollection = func(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            db, err := infra.Cloner()
            if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
            }
            collection, err := NewDeviceCollection(db)

            if err != nil {
                db.Session.Close()
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
            }
            ctx := context.WithValue(r.Context(), DeviceRepoKey, collection)
            go func() {
                select {
                case <-ctx.Done():
                    collection.Session.Close()
                }
            }()

            next.ServeHTTP(w, r.WithContext(ctx))
        })
    }
于 2016-11-28T19:58:47.930 に答える