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));
            }
        });
    }
7
  • So you want to fetch all recommendation records which game I'd is 1?? Commented Apr 30, 2017 at 15:57
  • yes exactly and If possible I would like to filter the fields of each object in the recommendations array in result. If not possible then its fine either way @thedarkcoder Commented Apr 30, 2017 at 16:06
  • See this link stackoverflow.com/questions/12629692/… Commented Apr 30, 2017 at 16:14
  • @thedarkcoder I have already written that elemMatch return only first match in the array not multiple. Commented Apr 30, 2017 at 16:17
  • See the link shows use of elemmatch in nested way.. Commented Apr 30, 2017 at 16:19

1 Answer 1

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/

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

8 Comments

looks promising. But this will search the entire database. How to limit it to search in the specific document. _id:"someId"
Keep your $match stage and add the $project stage after. Updated answer
I copied the code and its returning an empty array.
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.
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.
|

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.