英文:
How to create an index of pair unique for Mongodb?
问题
我正在使用MongoDB工作,我想在两个字段上创建一个唯一的键对。
以下是我目前所做的:
func (repository *TranslationRepository) createIndexes(collection *mongo.Collection) error {
models := []mongo.IndexModel{
{
Keys: bson.D{{"object_id", 1}, {"object_type", 1}},
Options: options.Index().SetUnique(true),
},
{
Keys: bson.D{{"expire_at", 1}},
Options: options.Index().SetExpireAfterSeconds(0),
},
}
opts := options.CreateIndexes().SetMaxTime(10 * time.Second)
_, err := collection.Indexes().CreateMany(context.Background(), models, opts)
return err
}
然而,当我像这样插入两条记录时:
{
"object_id" : "abc",
"object_type": "SAMPLE"
}
{
"object_id" : "edf",
"object_type": "SAMPLE"
}
在数据库中,只会有一条记录:
{
"object_id" : "edf",
"object_type": "SAMPLE"
}
第二条记录已经覆盖了第一条记录。
以下是我插入记录的示例代码:
TranslationForm := entity.TranslationForm{
ObjectID: "ABC",
ObjectType: "SAMPLE",
SourceLanguage: "en",
TargetLanguage: "cn",
Content: "something",
ExpireAt: time.Now(),
}
res, err := repository.collection.InsertOne(context.TODO(), TranslationForm)
英文:
I am working with MongoDB, I want to make a pair unique on 2 field.
The below is what I have done so far :
func (repository *TranslationRepository) createIndexes(collection *mongo.Collection) error {
models := []mongo.IndexModel{
{
Keys: bson.D{{"object_id", 1}, {"object_type", 1}},
Options: options.Index().SetUnique(true),
},
{
Keys: bson.D{{"expire_at", 1}},
Options: options.Index().SetExpireAfterSeconds(0),
},
}
opts := options.CreateIndexes().SetMaxTime(10 * time.Second)
_, err := collection.Indexes().CreateMany(context.Background(), models, opts)
return err
}
However when I insert 2 records like this
{
"object_id" : "abc",
"object_type": "SAMPLE"
}
{
"object_id" : "edf",
"object_type": "SAMPLE"
}
In the database, there will be only 1 record of
{
"object_id" : "edf",
"object_type": "SAMPLE"
}
The second already overwrited the first
The below is my sample code of inserting a record
TranslationForm := entity.TranslationForm{
ObjectID: "ABC",
ObjectType: "SAMPLE",
SourceLanguage: "en",
TargetLanguage: "cn",
Content: "something",
ExpireAt: time.Now(),
}
res, err := repository.collection.InsertOne(context.TODO(), TranslationForm)
答案1
得分: 1
我应该管理你的情景。让我分享一个简单的程序来展示我所实现的内容。
package main
import (
"context"
"fmt"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type Object struct {
ObjectId string `json:"object_id" bson:"object_id"`
ObjectType string `json:"object_type" bson:"object_type"`
}
func main() {
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*10)
defer cancelFunc()
clientOptions := options.Client().ApplyURI("mongodb://root:root@localhost:27017")
mongoClient, err := mongo.Connect(ctx, clientOptions)
if err != nil {
panic(err)
}
defer mongoClient.Disconnect(ctx)
demoDb := mongoClient.Database("demodb")
defer demoDb.Drop(ctx)
myCollection := demoDb.Collection("myCollection")
defer myCollection.Drop(ctx)
// 创建索引
indexModel := mongo.IndexModel{
Keys: bson.D{
bson.E{
Key: "object_id",
Value: 1,
},
bson.E{
Key: "object_type",
Value: 1,
},
},
Options: options.Index().SetUnique(true),
}
idxName, err := myCollection.Indexes().CreateOne(ctx, indexModel)
if err != nil {
panic(err)
}
fmt.Println("索引名称:", idxName)
// 删除文档
defer func() {
if _, err := myCollection.DeleteMany(ctx, bson.M{}); err != nil {
panic(err)
}
}()
// 插入第一个文档
res, err := myCollection.InsertOne(ctx, Object{ObjectId: "abc", ObjectType: "SAMPLE"})
if err != nil {
panic(err)
}
fmt.Println(res.InsertedID)
// 插入第二个文档
// res, err = myCollection.InsertOne(ctx, Object{ObjectId: "abc", ObjectType: "SAMPLE"}) => ERROR
res, err = myCollection.InsertOne(ctx, Object{ObjectId: "def", ObjectType: "SAMPLE"}) // => OK!
if err != nil {
panic(err)
}
fmt.Println(res.InsertedID)
// 列出所有文档
var objects []Object
cursor, err := myCollection.Find(ctx, bson.M{})
if err != nil {
panic(err)
}
if err = cursor.All(ctx, &objects); err != nil {
panic(err)
}
fmt.Println(objects)
}
现在,我将总结所有的主要步骤:
- 定义了
Object
结构体,它是你所需的简化版本。请注意bson
注释是实际使用的注释。为了演示的目的,你可以安全地忽略json
注释。 - 与Mongo生态系统相关的设置:
- 创建上下文(带有超时)
- 客户端设置(连接到通过Docker运行的本地MongoDB实例)
- 创建名为
demodb
的数据库和名为myCollection
的集合。此外,我还延迟了在程序退出时删除这些内容的调用(仅用于清理)。
- 在
object_id
和object_type
字段上创建唯一的复合索引。请注意Options
字段,它使用SetUnique
方法声明了索引的唯一性。 - 添加文档。请注意,程序不允许插入具有相同字段的两个文档,你可以尝试注释/取消注释这些情况以进行确认。
- 最后,为了调试目的,我列出了集合中的文档,以检查第二个文档是否已添加。
希望这个演示能够解答你的疑问。如果有任何问题,请告诉我,谢谢!
英文:
I should have managed your scenario. Let me share a simple program to show off what I achieved.
package main
import (
"context"
"fmt"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type Object struct {
ObjectId string `json:"object_id" bson:"object_id"`
ObjectType string `json:"object_type" bson:"object_type"`
}
func main() {
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*10)
defer cancelFunc()
clientOptions := options.Client().ApplyURI("mongodb://root:root@localhost:27017")
mongoClient, err := mongo.Connect(ctx, clientOptions)
if err != nil {
panic(err)
}
defer mongoClient.Disconnect(ctx)
demoDb := mongoClient.Database("demodb")
defer demoDb.Drop(ctx)
myCollection := demoDb.Collection("myCollection")
defer myCollection.Drop(ctx)
// create index
indexModel := mongo.IndexModel{
Keys: bson.D{
bson.E{
Key: "object_id",
Value: 1,
},
bson.E{
Key: "object_type",
Value: 1,
},
},
Options: options.Index().SetUnique(true),
}
idxName, err := myCollection.Indexes().CreateOne(ctx, indexModel)
if err != nil {
panic(err)
}
fmt.Println("index name:", idxName)
// delete documents
defer func() {
if _, err := myCollection.DeleteMany(ctx, bson.M{}); err != nil {
panic(err)
}
}()
// insert first doc
res, err := myCollection.InsertOne(ctx, Object{ObjectId: "abc", ObjectType: "SAMPLE"})
if err != nil {
panic(err)
}
fmt.Println(res.InsertedID)
// insert second doc
// res, err = myCollection.InsertOne(ctx, Object{ObjectId: "abc", ObjectType: "SAMPLE"}) => ERROR
res, err = myCollection.InsertOne(ctx, Object{ObjectId: "def", ObjectType: "SAMPLE"}) // => OK!
if err != nil {
panic(err)
}
fmt.Println(res.InsertedID)
// list all docs
var objects []Object
cursor, err := myCollection.Find(ctx, bson.M{})
if err != nil {
panic(err)
}
if err = cursor.All(ctx, &objects); err != nil {
panic(err)
}
fmt.Println(objects)
}
Now, I'm gonna recap all of the main steps:
- Definition of the
Object
struct which is a simplified version of what you need. Please note thebson
annotations that are the ones actually used. For the sake of this demo, you can safely omit thejson
ones. - The setup related to the Mongo ecosystem:
- Context creation (with a timeout)
- Client set up (connection to a local MongoDB instance run via Docker)
- Creation of a database called
demodb
and a collection calledmyCollection
. Plus, I deferred the calls to delete this stuff while exiting the programs (just for clean-up).
- Creation of a unique compound index on the fields
object_id
andobject_type
. Pay attention to theOptions
field that states the uniqueness of the index with the methodSetUnique
. - Adding documents. Please note that the program won't allow you to insert two documents with the same fields as requested. You can try to comment/uncomment the cases just to have another confirmation.
- For debug purposes, I finally list the documents in the collection to check whether the second document has been added or not.
I hope that this demo has clarified a few your doubts. Let me know & thanks!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论