Get last inserted element from mongodb in GoLang using FindOne and $natural - mongodb

I'm trying to retrieve the last inserted document using FindOne as suggested elsewhere:
collection.FindOne(ctx, bson.M{"$natural": -1})
Get last inserted element from mongodb in GoLang
Here is my example:
var lastrecord bson.M
if err = collection.FindOne(ctx, bson.M{"$natural": -1}).Decode(&lastrecord); err != nil {
log.Fatal(err)
}
fmt.Println(lastrecord)
Unfortunately I get the following error:
(BadValue) unknown top level operator: $natural
I'd prefer to use FindOne if possible.

You want to sort using natural order, yet you specify it as a filter, which is what the error says.
To use $natural to specify sorting:
opts := options.FindOne().SetSort(bson.M{"$natural": -1})
var lastrecord bson.M
if err = coll.FindOne(ctx, bson.M{}, opts).Decode(&lastrecord); err != nil {
log.Fatal(err)
}
fmt.Println(lastrecord)

Related

How to update many by objectid in mongodb using go driver

I want to bulk update collection by slice of objectid
Here is the function for updatemany
func BulkDeleteEmailContentFieldByIds(ids []primitive.ObjectID) error {
filter := bson.M{"_id": bson.M{"$in": ids}}
update := bson.D{{"$unset", bson.D{{"email_content", 1}}}}
result, err := collection.UpdateMany(ctx, filter, update)
if err != nil {
return err
}
pp.Printf("Bulk delete removed %v document(s)\n", result.ModifiedCount)
return nil
}
var trackingLogIds []primitive.ObjectID
for _, v := range userDocs {
wg.Add(1)
go func(v bson.M) {
defer wg.Done()
// do something to return objectID
trackingLogIds = append(trackingLogIds, emaDoc["_id"].(primitive.ObjectID))
}(v)
}
emadb.BulkDeleteEmailContentFieldByIds(trackingLogIds)
Is the slice trackingLogIds is the correct way to search for documents with objectId
And is the query for updatemany i doing is right?
If not then how can i improve it.
Thanks
I had test the function i provided and its working as expected.
Find all document in slice of objectid and unset the field email_content

Is there a way that can find one document and clone it with changing id/value in mongodb with Go

suppose I have code like this:
var result bson.M
err := coll.FindOne(context.TODO(), filter).Decode(&result)
if err != nil {
panic(err)
}
// somehow I can change the _id before I do insertOne
if _, err := coll.InsertOne(context.TODO(), result); err != nil {
panic(err)
}
is there a way I can insertOne without knowing the data struct? But I have to change the _id before I insert it.
The ID field in MongoDB is always _id, so you may simply do:
result["_id"] = ... // Assign new ID value
Also please note that bson.M is a map, and as such does not retain order. You may simply change only the ID and insert the clone, but field order may change. This usually isn't a problem.
If order is also important, use bson.D instead of bson.M which retains order, but finding the _id is a little more complex: you have to use a loop as bson.D is not a map but a slice.
This is how it could look like when using bson.D:
var result bson.D
// Query...
// Change ID:
for i := range result {
if result[i].Key == "_id" {
result[i].Value = ... // new id value
break
}
}
// Now you can insert result

Search documents using $gt filter with go-mongodb driver

I'm stuck at a probably simple problem: If I filter this in mongodb compass (filter {dateTime:{$gt: new Date("2020-11-23T12:31:38")}}):
It returns 556 documents.
Trying to create a cursor in Go that have those documents is proving to be quite hard!
I've this right now:
cursor, err := coll.Find(context.Background(), bson.M{"dateTime": bson.M{"$gt": "new Date("+ date + ")"}}, opt)
if err != nil {
fmt.Println("Err creting database: ", err)
return nil, err
}
if cursor.Next(context.Background()) {
fmt.Println("Cursor0!")
cursor.Next(context.Background())
}
cursor1, err := coll.Find(context.Background(), bson.M{}, opt)
if err != nil {
fmt.Println("Err creting database: ", err)
return nil, err
}
if cursor1.Next(context.Background()) {
fmt.Println("Cursor1!")
cursor.Next(context.Background())
}.
I've tried, along other different tries, to put the filter just as bson.M{"dateTime": bson.M{"$gt": date}}, along other similar tryes, but they also returned 0 documents. The date variable have exacly the date used in the mongodb compass filter.
I created another cursor, with no filter, just to control if the connection with mongo is ok, and to see if it returns any documents when it has no filter, and it does return documents. Does anyone knows the answer to this one?
Thanks!!
new Date("2020-11-23T12:31:38") is JavaScript syntax. You need to use the proper Go syntax for creating timestamps.
The problem was that I was dealling with more than 1 Collection, and in one the date was saved as string, and in the other, as date. In the one that the date s saved as string, no surprise, we have to send the date as string too, some logic to when date is in mongo as Date

How to check if a record exists with golang and the offical mongo driver

I'm using the official mongo driver in golang, and am trying to determine if a record exists. Unfortunately the documentation doesn't explain how to do this. I'm attempting to do it with FindOne, but it returns and error when no results are found, and I don't know how to distinguish that error from any other error (short of comparing strings which feels wrong. What's the right way to check if a document exists in mongo with the official golang driver?
Here's my code.
ctx := context.Background()
var result Page
err := c.FindOne(ctx, bson.D{{"url", url}}).Decode(&result)
fmt.Println("err: ", err)
// how do I distinguish which error type here?
if err != nil {
log.Fatal(err)
}
Here's the answer.
var coll *mongo.Collection
var id primitive.ObjectID
// find the document for which the _id field matches id
// specify the Sort option to sort the documents by age
// the first document in the sorted order will be returned
opts := options.FindOne().SetSort(bson.D{{"age", 1}})
var result bson.M
err := coll.FindOne(context.TODO(), bson.D{{"_id", id}}, opts).Decode(&result)
if err != nil {
// ErrNoDocuments means that the filter did not match any documents in the collection
if err == mongo.ErrNoDocuments {
return
}
log.Fatal(err)
}
fmt.Printf("found document %v", result)

Checking if data exists in a mongodb collection in goLang?

If i want to check if there currently exists at least one document in a collection, how would I go about doing this in GoLang?
The most performant way to check if documents exist in a collection is to use the EstimatedDocumentCount function on a collection because it gets an estimate from the collection's metadata.
You can do something like this:
count, err := collection.EstimatedDocumentCount(context.Background())
If the actual count of documents in the collection is important and you need more than just an estimate, it makes sense to look into the MongoDB aggregation framework.
You can do something like this which wraps the aggregation framework:
count, err := collection.CountDocuments(ctx, bson.M{})
if err != nil {
panic(err)
}
if count >= 1 {
fmt.Println("Documents exist in this collection!")
}
You could also try something like the following if you want to use the aggregation framework directly:
cursor, err := episodesCollection.Aggregate(ctx, []bson.D{
bson.D{{"$count", "mycount"}},
})
if err != nil {
panic(err)
}
var counts []bson.M
cursor.All(ctx, &counts)
fmt.Println(counts[0]["mycount"])