MongoDB Golang: FindOne() with nested Bson.M failed for 10% attempts, Bson.M+Bson.D or a single Bson.M always work, why?

224 Views Asked by At

Need some help to figure out why nested bson.M doesn’t work occasionally in FindOne().

For the following Golang structs stored in a MongoDb collection for type A:


type A struct {
 Id       primitive.ObjectID 
 Random1  string
 Parents  []B
 Random2  int
}

type B struct {
 Id       primitive.ObjectID 
 Random3  string
 Children []C
 Random4  int
}

type C struct {
 Random5  string
 Name     Name
 Random6  int
}

type Name struct {
  FirstName string
  LastName string
}

The following filter for FindOne(), which uses two bson.M, worked in most situations but failed to find a match in about 10% runs

filter1 := bson.M{
        "parents.0.chilren.0.name": bson.M{
            "first_name":  "Mike",
            "last_name": "Anderson",
        },
}

The following two filters alway work, where filter 2 uses bson.D inside bson.M, and filter 3 just uses one bson.M

filter2 := bson.M{
        "parents.0.chilren.0.name": bson.D{
            {Key: "first_name",  Value: "Mike"},
            {Key: "last_name",  Value: "Anderson"},
        },
}

filter3 := bson.M{
        "parents.0.chilren.0.name.first_name":  "Mike",
        "parents.0.chilren.0.name.last_name":  "Anderson",
}

I found a similar question in https://jira.mongodb.org/browse/GODRIVER-877 but still don’t understand the differences or root cause. Thanks for the help!

1

There are 1 best solutions below

2
Burak Serdar On

bson.M is a map, thus, the order of its elements are not guaranteed. Since you are comparing parents.0.chilren.0.name, which is a structure, the search criteria has to match exactly, with the order of fields in the criteria matching the order fields in the database. That's why when you use bson.M, it sometimes matches and sometimes not. When the search criteria matches the database field order, you get results, otherwise you don't.

That's the reason why the criteria with bson.D always matches, because it is based on a slice, so the order of fields are preserved.

The last search criteria compares individual fields, not a structure, so the order of fields are immeterial.