I am trying to get results sorted by datetime field using Golang mongo-driver, but I keep getting decoding error for the filed with the code below
type Source struct {
Name string
Url string
Crawl bool
Failure int64
Success int64
Processed primitive.DateTime `bson:"processed"`
LastHomeRefresh primitive.DateTime `bson:"lastHomeRefresh"`
}
func GetOneSource(coll *mongo.Collection) (source Source, err error) {
find := bson.D{{"crawl", true}}
opts := options.FindOne().SetSort(bson.D{{"processed", 1}})
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
err = coll.FindOne(ctx, find, opts).Decode(&source)
if err != nil {
log.Print(err)
}
return
}
On calling the function I get
error decoding key processed: cannot decode string into a DateTime
I am able to get results when sorting with other fields without any issue, but using either of datetime fields returns this err. Explicitly adding bson data to struct also did not help
What am I missing here? Any help is appreciated.
Hi @Frank_Martin , thanks for the question! I’ve put together the following in attempts to reproduce your use case:
package main
import (
"context"
"fmt"
"log"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type Source struct {
Crawl bool
Processed primitive.DateTime `bson:"processed"`
}
func main() {
opts := options.Client().ApplyURI("mongodb://localhost:27017")
client, err := mongo.Connect(context.Background(), opts)
if err != nil {
panic(err)
}
defer func() { _ = client.Disconnect(context.Background()) }()
// Insert some data to query.
coll := client.Database("testdb").Collection("coll")
coll.InsertOne(context.Background(), Source{
Crawl: true,
Processed: primitive.NewDateTimeFromTime(time.Now()),
})
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
find := bson.D{{"crawl", true}}
findopts := options.FindOne().SetSort(bson.D{{"processed", 1}})
var source *Source
err = coll.FindOne(ctx, find, findopts).Decode(&source)
if err != nil {
log.Print(err)
}
fmt.Println("processed: ", source.Processed)
}
The output is as I would expect:
pocessed: 1707260939662
The wire message that the Go Driver sends to the server is also as-expected:
{"find": "coll","filter": {"crawl": true},"limit": {"$numberLong":"1"},"singleBatch": true,"sort": {"processed": {"$numberInt":"1"}},"lsid": {"id": {"$binary":{"base64":"QRygb0e4QgivzS9BSeyAJw==","subType":"04"}}},"$clusterTime": {"clusterTime": {"$timestamp":{"t":1707261056,"i":1}},"signature": {"hash": {"$binary":{"base64":"AAAAAAAAAAAAAAAAAAAAAAAAAAA=","subType":"00"}},"keyId": {"$numberLong":"0"}}},"$db": "testdb"}
I have a few questions
-
Are you certain that the data you are querying has a datetime value for every source record’s processed field? You can check this with the following: db.<your coll>.aggregate([{ $group: { _id: { $type: "$processed" } } }]) . It’s worth noting that the server will sort data with string type before date and timestamp, you can see the specific rules here.
-
If the processed data type is uniform, what version of the Go Driver are you seeing this behavior?
1 Like
Hi Preston_Vasquez, thanks for your reply.
I am sorry for being late to this, but I figured out the solution to this was setting the date type as
time.Time
instead of
primitive.DateTime
to make it work.
I can confirm that field had correct record for every field type. I did not looked into this issue more once I got it working.
I don’t know if the reason is that data is written by different process in JS and then called here which is causing the conflict, but that should not be the case.