0

suppose the following schema

    {
        id:"14198959",
        user_name:"kikStart2X"
        recommendations:[
                    {
                        friend_id:"1419897878",
                        friend_name:"nitpick",
                        profile_picture:"some image data",
                        game_id:"1" , 
                        game_name:"Bunny Hop"
                    },
                    {
                            friend_id:"14198848418",
                            friend_name:"applePie",
                            profile_picture:"some image data",
                            game_id:"1" , 
                            game_name:"Bunny Hop"
                    }, //etc
                ]
    }

Now I have searched alot on the internet and am getting no where near the solution. I have started learning MongoDB So I guess I have a long way to go.

Following is the aggregation I wrote

            {
                $match:
                {
                    _id:data.userId
                }
            } , 
            {
                $unwind:"$recommendations"
            }, 
            {
                $match:
                {
                    "recommendations.game_id":data.gameId
                }
            }

To Get The Following Results result:

[
    {
        friend_id:"1419897878",
        friend_name:"nitpick",
        profile_picture:"some image data",

    },
    {
      friend_id:"14198848418",
      friend_name:"applePie",
      profile_picture:"some image data",                           
     }
], // etc

but I am getting NULL

data.userId and data.gameId are the variables that have user ID and game ID I am searching

I have used $elemMatch with find and It works fine but only returns one match and not multiple. So I started learning how to aggregate but found no luck What am I doing wrong and What Do I need to do.

EDIT:

My Function

getRecommendorOfGame:function(data , callback)
    {
        Players.aggregate([{
    $match: {
        id: data.userId
    }
}, {
    $project: {
        recommendations: {
            $map: {
                input: {
                    $filter: {
                        input: "$recommendations",
                        as: "resultf",
                        cond: {
                            $eq: ["$$resultf.game_id", data.gameId]
                        }
                    }
                },
                as: "resultm",
                in: {
                    friend_id: "$$resultm.friend_id",
                    friend_name: "$$resultm.friend_name",
                    profile_picture: "$$resultm.profile_picture",
                }
            }
        }
    }
}],
            function(err , res){
            if(!err)
            {
                if(res != null)
                {
                    callback(helperFunctions.returnObj("" , "RECOMMENDOR RETREIVED SUCCESSFULLTY" , {'FRIEND':res}));
                }
                else
                {
                    callback(helperFunctions.returnObj("ERROR" , "NO RECOMMENDOR FOUND FOR THIS GAME" , null));
                }
            }
            else
            {
                callback(helperFunctions.returnObj("ERROR" , err , null));
            }
        });
    }
Uzumaki Naruto
  • 753
  • 1
  • 9
  • 27

1 Answers1

2

You don't need $unwind + $match. Use $map + $filter instead.

The below query $filters the recommendations array for matching game_id values followed by $map to project the fields to output the expected response.

{
    $match: {
        _id: mongoose.Types.ObjectId(data.userId)
    }
}, {
    $project: {
        recommendations: {
            $map: {
                input: {
                    $filter: {
                        input: "$recommendations",
                        as: "resultf",
                        cond: {
                            $eq: ["$$resultf.game_id", data.gameId]
                        }
                    }
                },
                as: "resultm",
                in: {
                    friend_id: "$$resultm.friend_id",
                    friend_name: "$$resultm.friend_name",
                    profile_picture: "$$resultm.profile_picture",
                }
            }
        }
    }
}

Reference

https://docs.mongodb.com/manual/reference/operator/aggregation/filter/ https://docs.mongodb.com/manual/reference/operator/aggregation/map/

s7vr
  • 73,656
  • 11
  • 106
  • 127
  • looks promising. But this will search the entire database. How to limit it to search in the specific document. _id:"someId" – Uzumaki Naruto Apr 30 '17 at 17:31
  • Keep your $match stage and add the $project stage after. Updated answer – s7vr Apr 30 '17 at 17:32
  • I copied the code and its returning an empty array. – Uzumaki Naruto Apr 30 '17 at 17:35
  • Can you check the values that you are passing ? Make sure values are string not numbers. Try with hardcoded values first and then you can verify your input values. – s7vr Apr 30 '17 at 17:36
  • Yes they are in string. Same values work fine with elemMatch if I wanted only first match. But its been 3 hours and I cant return multiple matches. – Uzumaki Naruto Apr 30 '17 at 17:39
  • Change field name in `$match` from `_id` to `id`. It works for me after changing. Updated answer. – s7vr Apr 30 '17 at 17:40
  • Still an empty array. How is it working on your end I wonder! – Uzumaki Naruto Apr 30 '17 at 17:47
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/143042/discussion-between-veeram-and-uzumaki-naruto). – s7vr Apr 30 '17 at 17:49