2

I am trying to get users in a certain age range via aggregation.

Edit: I am able to work through mongo shell, query works fine however I am not able to make it work with go

This code gives me "missing type in composite literal" error.

What am I missing here?

lte := 10
gte := 0

operations := []bson.M{
    {
        "$match":{
            "$and":[]interface{}{
                bson.M{"age":{"$gte":gte}},
                bson.M{"age":{"$lte":lte}},
            },
        },
    },
    {
        "$group":bson.M{"_id":"$user_id"},
    },

}

r := []bson.M{}

pipe := c.Pipe(operations)
err := pipe.All(&r)
if err != nil {
    logrus.Errorf("Error:  %v", err)
    return err
}
6
  • you are grouping by user_id but I don't see where you are selecting that as a result value Commented Mar 21, 2016 at 22:49
  • Please add an example document by editing your question. Commented Mar 21, 2016 at 22:58
  • @obi1 I am not sure I understand, can you elaborate ? Commented Mar 21, 2016 at 22:59
  • 1
    @MarkusWMahlberg, My question arises due to the fact that this code does not compile. I am not sure why you need an example document here. Commented Mar 21, 2016 at 23:02
  • @ceroloy Simply to make sure you actually do have a field named user_id and to prevent lengthy discussions. ;) Commented Mar 21, 2016 at 23:04

2 Answers 2

3

You have not defined "each" pipeline stage as a bson.M. It's an "array" of bson.M, hence the error:

operations := []bson.M{
    bson.M{
        "$match": bson.M{
            "date": bson.M{ "$gte": gte, "$lte": lte }
        }
    },
    bson.M{
        "group": bson.M{ "_id": "$user_id" }
    }
}

Also $and is not necessary. ALL MongoDB query conditions are already an "AND" expression anyway. The combination of $gte and $lte as keys in the same object expression is already an AND condtion on the same "date" property. Just as would be the addition of more keys within the $match object.

In the JavaScript shell, this is the same as:

var operations = [
    { "$match": { "date": { "$gte": gte, "$lte": lte } } },
    { "$group": { "_id": "$user_id" } }
];

So you need to remember that every JavaScript object notation {} equals a .bson.M{} statement. That's how you notate BSON objects in go with this libary.

Note: { "$group": { "_id": "$user_id } } is not going to do anything meaningful other than just return each "distinct" "user_id" value. So you likely want more accumulator options in any real result

Sign up to request clarification or add additional context in comments.

3 Comments

Unfortunately it did not work. I am trying to get distinct users in the given age range that is why I used group? Is that a mistake too?
@cemre The question you asked was about was about a composite literal with the expression you had. I gave you a solution that solved this. I have also rolled back your question revision as that is extremely rude. This is not a threaded discussion. You ask a question and someone answers it, then you accept it an move on. If you have other questions then Ask another question. Do not change your questions here from what you originally ask. People are nice enough to answer, so be nice back.
In addition, no your answer did not solved my problem since you modified the conditional part. I was originally trying to learn about using conditionals in the query and your answer just removes the part I am trying to learn.
-1

I believe this is what you want:

operations := []bson.M{
    bson.M{
        "$match":bson.M{
            "$and":[]interface{}{
                bson.M{"age":bson.M{"$gte":gte}},
                bson.M{"age":bson.M{"$lte":lte}},
            },
        },
    },
    bson.M{
        "$group":bson.M{"_id":"$user_id"},
    },

}

You simply forgot bson.M before "$and".

Edit: Looks like the ages too, I went ahead and fixed those.

Edit2: I missed more bson.M's than the initial 3 missing that I saw.

1 Comment

It missed more than just one bson.M, This again would simply not compile, as well as not noting that the $and is completely unnecessary

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.