Return entire MongoDB document based on the value inside an array

I have a bunch of group documents in my MongoDB. Inside those group documents each, there is an array of users. This array of users contains JSON objects that have the id values of the users currently part of the group.

I have a route in NodeJs that receives an ID, and this has to search through all groups and return those groups that have that ID inside the user's array.

How can I do this? This is the snippet of code of the object:

Group document:

{
"_id" : ObjectId("59d946c2a92b6c0f48feef19"),
"title" : "Grupo",
"group_id" : "1",
"params" : [],
"users" : [ 
    {
        "api_id" : "1",
        "_id" : ObjectId("59d946c2a92b6c0f48feef1a")
    }
],
"__v" : 0
}

User document:

{
"_id" : ObjectId("59d9035f25691a373073f671"),
"api_id" : "0",
"user" : "",
"password" : "",
"params" : {
    "name" : "Christian",
    "phone" : "23453453345234234",
    "firebase" : "KEY FOR FIREBASE GOES HERE"
},
"__v" : 0

}

Which query can I use to do this? I am passing only the api_id. I need to return all groups in a JSONArray format, which I can easily do, but I need to know how to search for it.

Upvotes: 0

Views: 63

Answers (2)

arvin karimi
arvin karimi

Reputation: 229

i think you could use aggregate function. check this please

db.collection.aggregate([
    {
        "$match": {
            "users._id": ObjectId("59d946c2a92b6c0f48feef1a")
        }
    },
    {
        "$unwind": "$users"
    },
    {
        "$project": {
            "_id": 1,
            "users": 1
        }
    }

])

another solution is elemMatch function

model.find().elemMatch('users', {_id:"59d946c2a92b6c0f48feef1a"}).exec()

or

model.find({users:{$elemMatch:{_id:"59d946c2a92b6c0f48feef1a"}}}).exec()

Upvotes: 0

Amr Labib
Amr Labib

Reputation: 4073

You can use mongodb aggregate

Check the code below this will return all groups where it contains a user with a matching api_id

db.parents.aggregate([{
        $unwind: {
            path: "$users"
        }
    },
    {
        $project: {
            _id: 1,
            title: 1,
            group_id: 1,
            user_id: "$users._id",
            user_api_id: "$users.api_id",
            params: 1
        }
    },
    {
        $match: { user_api_id: "<Place your api id here>" }
    },
    {
        $group: {
            _id: { _id: "$_id", group_id: "$group_id", title: "$title", user_api_id: "$user_api_id", params: "$params" }
        }
    },
    {
        $project: {
            _id: "$_id._id",
            params: "$_id.params",
            group_id: "$_id.group_id",
            title: "$_id.title",
            user_api_id: "$_id.user_api_id"
        }
    }
])

Quick explanation:

$unwind: this operation will flatten users array so the result from this operation will be list of group documents each with single user

$project: this operation will give you the ability to rename documents fields so instead of having users object inside each group document you will have a field called user_id and user_api_id inside each document.

$match : this operation will filter documents based on specific field, in our case user_api_id

$group : this operation will group all documents with the same _id, group_id, title, user_api_id and params, this grouping is done only to avoid duplicate documents ... we might get duplicate group documents if a group document contains more than 1 user with the same api_id

For more info about mongodb operators check mongodb documentation

Upvotes: 1

Related Questions