I. Len
I. Len

Reputation: 1

Can i aggregate two mongodb queries in one query using golang (mgo)?

I use golang and mgo, mongodb version is 3.2.9

For example i have two documents in one collection:

{"groupId" : 4, "name" : "email", "value" : "[email protected]"}

{"groupId" : 4,"name" : "phoneNumber","value" : "000000000"}

I know phoneNumber (value and name) and I need to find email (value). It can be simple done in two queries: first by phoneNumber I found groupId and then by groupId i found email. Is it possible to do it in one query (using golang and mgo)?

Upvotes: 0

Views: 1364

Answers (1)

chridam
chridam

Reputation: 103335

Yes, you would need to run an aggregation pipeline of the form:

var pipeline = [    
    {
        "$group": {
            "_id": "$groupId",
            "entries": {
                "$push": {
                    "name": "$name",
                    "value": "$value"
                }
            }
        }
    },
    {
        "$match": {
            "entries.name" : "phoneNumber", 
            "entries.value" : "000000000"
        }
    },
    {
        "$project": {
            "item": {
                "$arrayElemAt": [
                    {
                        "$filter": {
                            "input": "$entries",
                            "as": "item",
                            "cond": { "$eq": [ "$$item.name", "email" ] }
                        }
                    }, 0
                ]
            }
        }
    },
    {
        "$project": {
            "_id": 0,
            "email": "$item.value"
        }
    }

]);
db.collection.aggregate(pipeline);

Sample Output

{ "email" : "[email protected]" }

of which the equivalent mGo expression follows (untested):

pipeline := []bson.D{   
    bson.M{
        "$group": bson.M{
            "_id": "$groupId",
            "entries": bson.M{
                "$push": bson.M{
                    "name": "$name",
                    "value": "$value"
                }
            }
        }
    },
    bson.M{
        "$match": bson.M{
            "entries.name" : "phoneNumber", 
            "entries.value" : "000000000"
        }
    },
    bson.M{
        "$project": bson.M{
            "item": bson.M{
                "$arrayElemAt": [
                    bson.M{
                        "$filter": bson.M{
                            "input": "$entries",
                            "as": "item",
                            "cond": bson.M{ "$eq": 
                                []interface{}{  "$$item.name", "email" }    
                            }
                        }
                    }, 0
                ]
            }
        }
    },
    bson.M{
        "$project": bson.M{
            "_id": 0,
            "email": "$item.value"
        }
    }
}

pipe := collection.Pipe(pipeline)
iter := pipe.Iter()

Upvotes: 0

Related Questions