2

enter image description here

i have tried a few method but it doesn't work. How to find object from 2 array. My attempt:

Message.find({$and : [{_id : id}, {"users._id" : userID}]})

My Message Schema

const contentSchema = new Schema({
    ismy : Boolean,
    message : String
},{ timestamps: true });


const receiverSchema = new Schema({
    _id : String,
    messages : [contentSchema]
});


const messageSchema = new Schema({
    _id : String,
    users : [receiverSchema]
});

module.exports = mongoose.model('Message',messageSchema);

Returned All document but i want document that is with "_id": "5f38f3574644e92d0cbbc5be",

[
    {
        "_id": "20860f7806d19d7a29a8addc525f73b5",
        "users": [
            {
                "messages": [
                    {
                        "_id": "5f38f3574644e92d0cbbc5be",
                        "ismy": true,
                        "message": "aaaa",
                        "createdAt": "2020-08-16T08:50:31.317Z",
                        "updatedAt": "2020-08-16T08:50:31.317Z"
                    },
                    {
                        "_id": "5f38f39d4a11553f38da0ec8",
                        "ismy": true,
                        "message": "aaaa",
                        "createdAt": "2020-08-16T08:51:41.093Z",
                        "updatedAt": "2020-08-16T08:51:41.093Z"
                    },
                    {
                        "_id": "5f38f3a84a11553f38da0eca",
                        "ismy": true,
                        "message": "aaaaDASDASDSA",
                        "createdAt": "2020-08-16T08:51:52.407Z",
                        "updatedAt": "2020-08-16T08:51:52.407Z"
                    },
                    {
                        "_id": "5f38f3f3cb7eec3ffc61c050",
                        "ismy": true,
                        "message": "aaaaDASDASDSA",
                        "createdAt": "2020-08-16T08:53:07.809Z",
                        "updatedAt": "2020-08-16T08:53:07.809Z"
                    },
                    {
                        "_id": "5f38f3ffcb7eec3ffc61c053",
                        "ismy": true,
                        "message": "hahaha",
                        "createdAt": "2020-08-16T08:53:19.781Z",
                        "updatedAt": "2020-08-16T08:53:19.781Z"
                    }
                ],
                "_id": "9471e1b040fa962df160903066e75778"
            },
            {
                "messages": [],
                "_id": "11111111111"
            }
        ],
        "__v": 4
    }
]
6
  • Welcome to SO - your code/attempts would be helpful. Are you using mongoose or plain node mongodb-driver? Commented Aug 16, 2020 at 11:48
  • i use mongoose . i tried with $and operator but still doesn't work. like this Message.find({$and : [{_id : id}, {"users._id" : userID}]}) Commented Aug 16, 2020 at 11:50
  • Can you add your schema-definition for Message? Commented Aug 16, 2020 at 12:03
  • i added schema . i am new in stackoverflow. sorry for my bad question :( Commented Aug 16, 2020 at 12:11
  • Looks better now after the edit, but can you explain what it doesn't work mean? Are no records returned, are there errors? Commented Aug 16, 2020 at 12:27

1 Answer 1

1

There might be easier ways to do this, but what should work is the following aggregation-pipeline:

const ObjectId = require('mongoose').Types.ObjectId;
const res = await Message.aggregate(Message.aggregate([
{
    "$match": {
        // set the document id here
        _id: id
    }
},
{
    "$project": {
        "filteredMessages": {
            "$filter": {
                "input": {
                    "$map": {
                        "input": "$users",
                        "as": "user",
                        "in": {
                            "messages": {
                                "$filter": {
                                    "input": "$$user.messages",
                                    "as": "msg",
                                    "cond": {
                                // need to use ObjectId here, as the messages id's won't be plain string
                                        "$eq": ["$$msg._id", ObjectId("5f38f3574644e92d0cbbc5be")]
                                    }
                                }
                            }
                        }
                    },
                },
                "as": "filteredUser",
                "cond": {
                    "$and": [
                        {"$gt": [{"$size": "$$filteredUser.messages"}, 0]}
                    ]
                }
            }
        }
    }
}
]);

What I'm doing here is applying $filter and $map - $map is needed because the inner messages array can change as a result of the filtering, and the users array of course does not match the conditions when the messages-array was changed.

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

Comments

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.