当前位置: 首页 > 面试题库 >

在上下文中使用mgo

易阳朔
2023-03-14
问题内容

我一直在使用mgo作为我的API,但我在MongoDB中看到了许多当前连接(同时使用少于5个设备进行测试)。通过db.serverStatus().connections在Mongo服务器上执行,我得到:{ "current" : 641, "available" : 838219, "totalCreated" : 1136 }。在下面,我将我的问题记录在mgo的Github中(问题#429):

我在Web服务器中使用mgo的方式是否正确?如果没有,您能举一个完整的例子吗?

此代码不起作用,将其视为几乎伪代码(由于缺少诸如导入的部分或配置来自何处和模型),但这正是我使用mgo的方式。

我必须澄清,我正在构建一个供多个移动设备和Web应用程序使用的API。

main.go

func main() {
    mongoDBDialInfo := &mgo.DialInfo{
        Addrs:    []string{config.DatabaseURL},
        Timeout:  60 * time.Second,
        Database: config.DatabaseName,
        Username: config.DatabaseUsername,
        Password: config.DatabasePassword,
    }

    db, err := mgo.DialWithInfo(mongoDBDialInfo)

    if err != nil {
        log.Fatal("Cannot Dial Mongo: ", err)
    }

    defer db.Close() 
    db.SetMode(mgo.Monotonic, true)

    phoneIndex := mgo.Index{
        Key:        []string{"pp"},
        Unique:     true,
        DropDups:   true,
        Background: true,
        Sparse:     true,
    }

    err = db.DB(config.DatabaseName).C("users").EnsureIndex(phoneIndex)
    if err != nil {
        panic(err)
    }

    router := mux.NewRouter()
    router.HandleFunc("/login", publicWithDB(login, db)).Methods("POST")

    if err := http.ListenAndServe(":5000", router); err != nil {
        log.Fatal(err)
    }
}

func publicWithDB(fn http.HandlerFunc, db *mgo.Session) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        dbsession := db.Copy()
        defer dbsession.Close()
        fn(w, r.WithContext(context.WithValue(r.Context(), contextKeyDatabase, dbsession)))
    }
}

func login(w http.ResponseWriter, r *http.Request) {
    r.ParseForm() // Parses the request body
    device := r.Form.Get("device")

    var deviceid bson.ObjectId
    if bson.IsObjectIdHex(device) {
        deviceid = bson.ObjectIdHex(device)
    }

    db := r.Context().Value(contextKeyDatabase).(*mgo.Session)

    var device models.Device
    err := db.DB(config.DatabaseName).C("devices").FindId(deviceid).One(&device)

    w.WriteHeader(200)
    w.Write([]byte(utils.ResponseToString(models.Response{Status: 200, Message: "asdasd", Data: device})))

}

我发布此消息是因为找不到完整的实现。


问题答案:

这是我如何看待自己和其他人在Go中构建Web应用程序的示例。此代码未经测试,仅作为示例。它缺少导入,并且可能有错误。

编辑 添加了一个中间件示例。

main.go

package main

func main() {
    mongoDBDialInfo := &mgo.DialInfo{
        Addrs:    []string{config.DatabaseURL},
        Timeout:  60 * time.Second,
        Database: config.DatabaseName,
        Username: config.DatabaseUsername,
        Password: config.DatabasePassword,
    }

    db, err := mgo.DialWithInfo(mongoDBDialInfo)

    if err != nil {
        log.Fatal("Cannot Dial Mongo: ", err)
    }

    defer db.Close() 
    db.SetMode(mgo.Monotonic, true)

    phoneIndex := mgo.Index{
        Key:        []string{"pp"},
        Unique:     true,
        DropDups:   true,
        Background: true,
        Sparse:     true,
    }

    err = db.DB(config.DatabaseName).C("users").EnsureIndex(phoneIndex)
    if err != nil {
        panic(err)
    }

    mgoAdapter := mongo.NewAdapter(db, config.DatabaseName)
    deviceStore := mongo.NewDeviceStore(mgoAdapter)
    userStore := mongo.NewUserStore(mgoAdapter)

    loginController := controllers.NewLoginController(deviceStore)

    router := mux.NewRouter()
    router.HandleFunc("/login", middleware.AuthorizeUser(userStore)(http.HandlerFunc(loginController.Login)).Methods("POST")

    if err := http.ListenAndServe(":5000", router); err != nil {
        log.Fatal(err)
    }
}

控制器/login.go

package controllers

type LoginController struct { 
    store DeviceStore
}

func NewLoginController(store stores.DeviceStore) *LoginController {
    return &LoginController{
        store: store,
    }
}

func (c *LoginController) Login(w http.ResponseWriter, r *http.Request) {
    r.ParseForm() // Parses the request body
    device := r.Form.Get("device")
    data, err := c.store.FindByDevice(device)

    var respose models.Response
    if err != nil {
        w.WriteHeader(500)
        response = models.Response{Status: 500, Message: fmt.Sprintf("error: %s", err)}
    } else if data == nil {
        w.WriteHeader(404)
        response = models.Response{Status: 404, Message: "device not found"}
    } else {
        response = models.Response{Status: 200, Message: "device found", Data: data}
    }

    // Write sets header to 200 if it hasn't been set already
    w.Write([]byte(utils.ResponseToString(response)))
}

store / stores.go

package stores

type DeviceStore interface {
    FindByDevice(device string) (*models.Device, error)
}

type UserStore interface {
    FindByToken(token string) (*models.User, error)
}

中间件/auth.go

package middleware

func AuthorizeUser(store stores.UserStore) func(h *http.Handler) http.Handler {
    return func(h *http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            // Logic for authorizing user
            // Could also store user in the request context
        })
    }
}

mongo / mongo.go

package mongo

type Adapter struct {
    session      *mgo.Session
    databaseName string
}

func NewAdapter(session *mgo.Session, dbName string) *Adapter {
    return &Adapter{session: session, databaseName: dbName}
}

type deviceStore struct {
    *Adapter
}

func NewDeviceStore(adapter *Adapter) stores.DeviceStore {
    return &deviceStore{adapter}
}

const devices = "devices"

func (s *deviceStore) FindByDevice(d string) (*models.Device, err) {
    sess := s.session.copy()
    defer sess.close()

    var deviceID bson.ObjectId
    if bson.IsObjectIdHex(d) {
        deviceID = bson.ObjectIdHex(d)
    }

    var device models.Device
    err := db.DB(s.databaseName).C(devices).FindId(deviceID).One(&device)
    if err == mgo.ErrNotFound {
        return nil, nil
    }
    return &device, err
}

type userStore struct {
    *Adapter
}

const users = "users"

func NewUserStore(adapter *Adapter) stores.UserStore {
    return &userStore{adapter}
}

func (s *userStore) GetUserByToken(token string) (*models.User, error) {
    sess := s.session.copy()
    defer sess.close()

    var user models.User
    err := db.DB(s.databaseName).C(users).Find(bson.M{"token": token}).One(&user)
    if err == mgo.ErrNotFound {
        return nil, nil
    }

    return &user, err
}


 类似资料:
  • 问题内容: 如何获取片段中的上下文? 我需要用我的数据库其构造函数采用的背景下,但并没有工作,所以我能做些什么? 数据库构造函数 问题答案: 你可以使用,返回与关联的活动。 活动是(自扩展以来)。

  • 问题内容: 在SpringMVC应用程序中,有没有一种方法可以使用web.xml加载上下文? 问题答案: Spring可以轻松集成到任何基于Java的Web框架中。你需要做的就是在中声明并使用 设置要加载的上下文文件。 然后,你可以使用WebApplicationContext来获取bean的句柄。

  • 我使用PHP REST SDK进行快速签出,我的代码基于以下示例:http://paypal.github.io/PayPal-PHP-SDK/sample/doc/payments/CreatePaymentUsingPayPal.html 这工作得很好,除了我不确定如何将它与新的上下文结帐集成。据我所知,我只需要EC令牌,这样我就可以在上下文结帐时使用它,并获得像这样的网址,但是我找不到如何仅

  • 首先,我想说我从来没有使用过Next.js或context api,所以请耐心听我说。 我目前正在Next.js中开发一个web应用程序,其中有多个页面,每个页面都包含一个表单。我希望有某种全局状态,以便能够设置和更新每个表单的数据。所有表单数据一起 例如:第1页=名称,第2页=说明,... 从我在网上读到的内容来看,我认为使用上下文api就足够了,但我遇到了困难。当我在第一个表单上填写名字时,它

  • 我在我的Spring boot应用程序中使用OAuth2RestTemplate,并通过它使用一些资源,因为它封装了所有身份验证信息,所以我可以只发送请求,而不用担心令牌和其他身份验证内容。 在我并行发送请求之前,一切都很好。 由于OAuth2RestTemplate有一个作用域(它是本地的,因为它包含用户的会话相关信息),当我试图在多线程环境中使用它时,我得到以下异常 组织。springfram

  • 问题内容: 您能帮我用下面的代码吗?错误是: “不能在静态上下文中使用此” 问题答案: 参见,“ this”关键字指的是当前对象,这是由于正在执行哪种方法。不能使用类的实例调用静态方法。这就是为什么不能在上面的示例中以静态方法使用“ this”的原因,因为它试图打印当前未创建的当前实例。因此,我认为这就是为什么您会遇到编译时错误。