在Go中使用MongoDb默认驱动程序创建唯一索引

在Go中使用MongoDb默认驱动程序创建唯一索引,mongodb,go,indexing,go-echo,Mongodb,Go,Indexing,Go Echo,使用为某些数据创建唯一索引时遇到一些问题 我有一个这样的结构: type Product struct { ID primitive.ObjectID `json:"_id" bson:"_id"` Name string `json:"name" bson:"name"` Price float64 `json:"price" bson:"price"` Attribute []Att

使用为某些数据创建唯一索引时遇到一些问题

我有一个这样的结构:

type Product struct {
    ID        primitive.ObjectID `json:"_id" bson:"_id"`
    Name      string             `json:"name" bson:"name"`
    Price     float64            `json:"price" bson:"price"`
    Attribute []Attribute        `json:"attribute" bson:"attribute"`
    Category  string             `json:"category" bson:"category"`
}
然后我想为
name
属性创建一个唯一的索引。我尝试在我的
Create
函数(针对产品)中执行类似的操作

问题是,在创建产品之前,我不知道如何在上下文中将
indexModel
作为选项传递。另外,我不确定我正在做的事情是否只创建了一次索引(这就是我想要做的)。如果能为我指明正确的方向,我将不胜感激


我正在使用echo框架来支持Go,以防它提供更多的上下文

每次调用
create
函数时,您的代码都会尝试创建索引,这会起作用,但效率不高,因为索引只需要创建一次(或者如果它不存在的话)。我建议让建立DB连接的函数负责创建索引,或者让函数在初始化DB连接后立即运行,这样它只运行一次(当程序启动时)

由于
collection.Indexes().CreateOne(…)
方法在尝试创建已存在的索引时不会返回错误,因此可以使用此方法确保索引存在,类似于非正式MongoDB驱动程序的函数


或者,您可以按照Cahaba Data在中的建议,将索引创建作为一次性的DB管理任务,而不是应用程序的责任。我以前曾就此与一些同事进行过讨论,虽然我确实同意这在技术上是一项一次性的DB管理任务,但我仍然希望我的应用程序在启动时确保它所需的索引确实存在,如果没有,则创建它们。毕竟,如果有人忘记或创建错误的索引,我的应用程序可能会出现故障/瘫痪。它还提供了有关应用程序需要/使用哪些索引的良好文档,而不必与DB管理员进行沟通,并希望他/她/It会适当地注意到这一点。当然,您可以自由地形成自己的观点:)

是的,我认为创建索引是一次DBA/管理事件。这不是应用程序/代码任务。使用适当的权限登录mongo,创建索引,注销…就是这样。除了mongoshell命令之外,没有其他代码可以创建索引。

这是官方的MongoDB驱动程序,但是没有默认的。要有一个默认值,必须有一些驱动程序,当您不进行选择时将使用这些驱动程序。显然不是这样。哦,我明白你的意思了。感谢您指出:)如果多次创建同一索引,MongoDB或Go驱动程序实际上不会引发错误。在应用程序启动时创建所需的索引是安全的。好的,但最好在初始化数据库时创建索引,然后正常调用create函数,这应该可以解决问题。对吗?@StefanArentz-Hmmm,你说得对,我刚刚试过,Go驱动程序在创建已经存在的索引时确实不会返回错误。我会编辑我的answer@IkechukwuMadu是的,如果“正常”是指没有索引创建部分。
func Create(c echo.Context) error {

    //unique index here 
    indexModel, err := productCollection.Indexes().CreateOne(context.Background(),
        IndexModel{
            Keys:    bsonx.Doc{{"name", bsonx.Int32(1)}},
            Options: options.Index().SetUnique(true),
        })
    if err != nil {
        log.Fatalf("something went wrong: %+v", err)
    }

    //create the product here
    p := new(Product)
    if err := c.Bind(p); err != nil {
        log.Fatalf("Could not bind request to struct: %+v", err)
        return util.SendError(c, "500", "something went wrong", "failed")
    }
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    result, _ := productCollection.InsertOne(ctx, p)

    return util.SendSuccess(c, result.InsertedID)

}