Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use mongodb projections with Go and mgo?

Tags:

mongodb

go

bson

mgo

I am currently trying to extract a single object within a document array inside of mongodb. This is a sample dataset:

"_id" : ObjectId("564aae61e0c4e5dddb07343b"),
"name" : "The Races",
"description" : "Horse races",
"capacity" : 0,
"open" : true,
"type" : 0,
"races" : [
    {
        "_id" : ObjectId("564ab9097628ba2c6ec54423"),
        "race" : {
            "distance" : 3000,
            "user" : {
                "_id" : ObjectId("5648bdbe7628ba189e011b18"),
                "status" : 1,
                "lastName" : "Miranda",
                "firstName" : "Aramys"
            }
        }
    },
    {
        "_id" : ObjectId("564ab9847628ba2c81f2f34a"),
        "bet" : {
            "distance" : 3000,
            "user" : {
                "_id" : ObjectId("5648bdbe7628ba189e011b18"),
                "status" : 1,
                "lastName" : "Miranda",
                "firstName" : "Aramys"
            }
        }
    },{...}
]

I can successfully query using the following in mongo:

db.tracks.find({"_id": ObjectId("564aae61e0c4e5dddb07343b")}, {"races": { $elemMatch: {"_id": ObjectId("564ab9847628ba2c81f2f34a")}}}).pretty()

I am unable to do the same using mgo and have tried the following:

Using nesting (Throws: missing type in composite literal, missing key in map literal)

// Using nesting (Throws: missing type in composite literal, missing key in map literal)
c.Find(bson.M{{"_id": bson.ObjectIdHex(p.ByName("id"))}, bson.M{"races": bson.M{"$elemMatch": bson.M{"_id": bson.ObjectIdHex(p.ByName("raceId"))}}}}).One(&result)

// Using select (Returns empty)
c.Find(bson.M{"_id": bson.ObjectIdHex(p.ByName("id"))}).Select(bson.M{"races._id": bson.ObjectIdHex(p.ByName("raceId"))}).One(&result)

//As an array (Returns empty)
c.Find([]bson.M{{"_id": bson.ObjectIdHex(p.ByName("id"))}, bson.M{"races": bson.M{"$elemMatch": bson.M{"_id": bson.ObjectIdHex(p.ByName("raceId"))}}}}).One(&result)

I am using httprouter and p.ByName("...") invocations are parameters passed to the handler.

Thanks in advance.

like image 908
Aramys Avatar asked Jan 07 '23 04:01

Aramys


1 Answers

Would go with the Select method as the doc states that this enables selecting which fields should be retrieved for the results found, thus the projection using $elemMatch operator can be applied here in conjuction with Select, with your final query looking something like:

c.Find(bson.M{
    "_id": bson.ObjectIdHex(p.ByName("id"))
}).Select(bson.M{
    "races": bson.M{
        "$elemMatch": bson.M{
            "_id": bson.ObjectIdHex(p.ByName("raceId"))
        }
    }
}).One(&result)
like image 124
chridam Avatar answered Jan 09 '23 19:01

chridam