How do I set TTL indexes in a document using "mongo-go-driver"?
suppose here is my document model:
type Session struct {
ID primitive.ObjectID `json:"id,omitempty" bson:"_id,omitempty"`
AccessToken string `json:"access_token" bson:"access_token"`
ExpireOn int64 `json:"expire_on" bson:"expire_on"`
}
and here I am inserting new document:
sessionCollection := database.Collection(COLLECTION_SESSION)
_, err = sessionCollection.InsertOne(context.TODO(), s)
if err != nil {
responses.RespondWithERROR(w, http.StatusInternalServerError, err)
return
}
Now I want that this session will be removed after a few times.
I found the way to do that in documentation Expire Data from Collections by Setting TTL but can't figure out How to do the same thing in go using mongo-go-driver.
Related
Getting this error while binding mongodb document to GO Struct using docstore collection iterator.
Database: Azure CosmosDB mongoDb API
Go Driver: Docstore
Code details:
Cosmos DB Constructors Code
client, err := c.newClient(ctx, true)
if err != nil {
log.Error("error connecting to mongodb cluster", zap.Error(err))
return nil, err
}
database := client.Database(c.dbName)
collection := database.Collection(c.collName)
return mongodocstore.OpenCollection(collection, "", nil)
Go struct for mapping with Mongo Db document
type utterance struct {
ID primitive.ObjectID `docstore:"_id,omitempty"`
User string `docstore:"user,omitempty"`
Locale string `docstore:"Locale,omitempty"`
Text string `docstore:"Text,omitempty"`
Source string `docstore:"Source,omitempty"`
Timestamp time.Time `docstore:"Timestamp,omitempty"`
DocstoreRevision interface{}
}
MondoDb Document
{
"_id" : ObjectId("60d5e18539864e948a8851a6"),
"User" : "auth0|6049b5ef5d79540071db6a0a",
"Locale" : "en_US",
"Text" : "Hi",
"Source" : "UTTERANCE_SOURCE_USER",
"Timestamp" : {
"$date" : 1624629637002
},
"DocstoreRevision" : "bf3b35d8-54ed-4a23-a08f-7d41b5c34085"
}
Method to call the docstore collection and iterate
i := s.collection.Query().Get(ctx)
defer i.Stop()
var results []*services.Utterance
for {
fmt.Println("for every document: ")
//var native utterance
doc := &utterance{}
err := i.Next(ctx, doc) //error at this line
if err == io.EOF {
break
} else if err != nil {
fmt.Println(“getting to this err block“)
return nil, err
}
u := doc.ToProto()
results = append(results, u)
}
Try setting the ID to a pointer type:
type utterance struct {
ID *primitive.ObjectID `docstore:"_id,omitempty"`
User string `docstore:"user,omitempty"`
Locale string `docstore:"Locale,omitempty"`
Text string `docstore:"Text,omitempty"`
Source string `docstore:"Source,omitempty"`
Timestamp time.Time `docstore:"Timestamp,omitempty"`
DocstoreRevision interface{}
}
Probably when you create the struct to be decoded the primitive.ObjectID is being initialized and the driver don't know to decode it.
And be careful. The docstore is a generic Document driver. It is not specific for MongoDB. So it probably don't work well with MongoDB specific types.
Reading the driver for mongodb https://pkg.go.dev/gocloud.dev/docstore/mongodocstore
There is a way to set what is stored in the _id field. I understand docstore don't know how to decode ObjectID from MongoDB.
I have Go code that connects to a mongodb database.
The problem is that when I'm trying to get a record from the collection there is an "_id" field of the ObjectId type, but in the mgo driver ObjectId is
type ObjectID [12]byte
but when I'm trying to get record Go says:
reflect.Set: value of type []uint8 is not assignable to type ObjectID
I have tried to create my own []uint8 type but I have no idea how to convert []uint8 ("ObjectId") to string or to find some record by those ids.
// ObjectId type that mongodb wants to see
type ObjectID []uint8
// model
type Edge struct {
ID ObjectID `bson:"_id"`
Name string `bson:"name"`
StartVertex string `bson:"startVertex"`
EndVertex string `bson:"endVertex"`
}
// method for getting record by those id
session, err := mgo.Dial(config.DatabaseURL)
if err != nil {
fmt.Printf("Error is: %s", err)
}
defer session.Close()
session.SetMode(mgo.Monotonic, true)
//edges collection
e := session.DB(config.DatabaseName).C(config.EdgesCollection)
var result models.Edge
err = e.Find(bson.M{"_id": fmt.Sprintln("ObjectId('", id, "')")}).One(&result)
if err != nil {
fmt.Println("Error is: ", err)
}
You have to use the "predefined" bson.ObjectId to model values of MongoDB's ObjectId:
type Edge struct {
ID bson.ObjectId `bson:"_id"`
Name string `bson:"name"`
StartVertex string `bson:"startVertex"`
EndVertex string `bson:"endVertex"`
}
And when you query an object by ID whose type is MongoDB's ObjectId, use a value of type bson.ObjectId. And you may use the Collection.FindId() method:
var id bson.ObjectId = ...
err = e.FindId(id).One(&result)
See details here: Find by id with mgo; and MongoDB slice query into golang
I have the following struct
type Account struct {
ID primitive.ObjectID `json:"id" bson:"_id"`
Email string `json:"email"`
Password string `json:"password"`
}
and the following function
func (a *Account) Create() map[string]interface{} {
if resp, ok := a.Validate(); !ok {
return resp
}
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(a.Password), bcrypt.DefaultCost)
a.Password = string(hashedPassword)
users := db.Collection("users")
insertResult, err := users.InsertOne(context.TODO(), a)
if err != nil {
return utils.Message(false, "Error inserting user document "+err.Error())
}
... more code down hre
}
The problem I am having is that I can insert the first account, but any account after that can't be inserted due to a dup key error on the _id field. I know that mongoDB will auto generate an _id field and will use the one provided if there is an id. In my case in this create function, the a.ID (_id) is always be NilValue "_id" : ObjectId("000000000000000000000000")
Is there any way mongoDB can generate an _id for me even if I provide and ID field with the nil value?
I need the Account.ID `bson: "_id"` property on there so I can decode it when I am reading from mongoDB such as
func GetUser(email string) *Account {
account := &Account{}
users := db.Collection("users")
filter := bson.D{{"email", email}}
if err := users.FindOne(context.TODO(), filter).Decode(&account); err != nil {
return utils.Message(false, "Error Retrieving account for "+email)
}
// account.ID will be available due to the bson tag
}
I'd appreciate some feedback if I am doing this wrong and how I could do this better.
Thanks!
I found the problem. I did not add ```omitempty` to the bson tag.
It should be
type Account struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"`
Email string `json:"email"`
Password string `json:"password"`
}
I'm working with MGO (cause I didn't found anything better that it).
I'have played with it and have got some result but I don't understand how to get the _id (internal Mongo ObjectId) of document received?
For ex:
type FunnyNumber struct {
Value int
_id string
}
session, err := mgo.Dial("127.0.0.1:27017")
if err != nil {
panic(err)
}
defer session.Close()
// Optional. Switch the session to a monotonic behavior.
session.SetMode(mgo.Monotonic, true)
c := session.DB("m101").C("funnynumbers")
funnynumber := FunnyNumber{}
err = c.Find(bson.M{}).One(&funnynumber)
if err != nil {
log.Fatal(err)
}
fmt.Println("Id one:", funnynumber._id) // Nothing here? WHy? How to get it.
fmt.Println("Value one:", funnynumber.Value) // 62. It's OK!
Could someone help me, please? Ot where might I read some info about it? I haven't found anything in the MGO doc
Schema of my document is:
{ "_id" : ObjectId("50778ce69331a280cf4bcf90"), "value" : 62 }
Thanks!
Change _id variable to uppercase(ID) to make it exportable.
Use bson.ObjectID as its type.
Add tag for struct FunnyNumber Id variable.
field
Above three things should be done to get object Id value.
import "labix.org/v2/mgo/bson"
type FunnyNumber struct {
Value int `json:"value"`
Id bson.ObjectId `bson:"_id,omitempty"`` // only uppercase variables can be exported
}
Take a look at package BSON for more understanding on using bson tags when working with mongodb
I have a struct like this:
type SavedData struct {
ID bson.ObjectId `bson:"_id"`
Data string
Date time.Time
}
I also have my
collection := database.C("coll_name")
How do I retrieve the last inserted entry in this collection ?
Thank you
The accepted answer is 5 years old. This should work Today with mongodb driver
collection.FindOne(ctx, bson.M{"$natural": -1})
Apparently mongoDB is by default sorted by insertion time according to
this question so you can just skip the first N elements of the collection like so.
var myData SavedData
dbSize, err := collection.Count()
if err != nil {
return err
}
err = c.Find(nil).skip(dbSize-1).One(&myData)
if err != nil {
return err
}
or you can search in the reverse order
c.Find(bson.M{ "$natural": -1 }).One(&myData)
You have to use options with mongo-driver if you want to get the latest document in the collection
import(
...
"go.mongodb.org/mongo-driver/mongo/options"
)
myOptions := options.FindOne()
myOptions.SetSort(bson.M{"$natural":-1})
collection.FindOne(ctx, bson.M{}, myOptions)