1

I have a chats collection which given down below

{
    "_id" : ObjectId("5a44e6545818041cde24aac9"),
    "messages" : [ 
        {
            "createdAt" : ISODate("2017-12-23T07:46:29.201Z"),
            "message" : "Hii",
            "userId" : "000000"
        }, 
        {
            "createdAt" : ISODate("2017-12-23T12:46:29.201Z"),
            "message" : "Bye gtg ttyl",
            "userId" : "111111"
        }, 
        {
            "createdAt" : ISODate("2017-12-24T07:46:29.201Z"),
            "message" : "Bye Take Care",
            "userId" : "000000"
        }
    ],
    "createdAt" : ISODate("2017-10-23T07:46:29.201Z"),
    "users" : [ 
        {
            "facebookId" : "0000000",
            "unread" : 0
        }, 
        {
            "facebookId" : "111111",
            "unread" : 0
        }
    ]
}

When I do this following query in nodejs

chats.aggregate( [ { $unwind : "$messages" },{ $unwind : "$users" } ])

I get an array which is something like this in which unwind opens my array something like this

[
    {
        "_id": "5a44e6545818041cde24aac9",
        "messages": {
            "createdAt": "2017-12-23T07:46:29.201Z",
            "message": "Hii",
            "userId": "000000"
        },
        "createdAt": "2017-10-23T07:46:29.201Z",
        "users": {
            "facebookId": "0000000",
            "unread": 0
        }
    },
    {
        "_id": "5a44e6545818041cde24aac9",
        "messages": {
            "createdAt": "2017-12-23T07:46:29.201Z",
            "message": "Hii",
            "userId": "000000"
        },
        "createdAt": "2017-10-23T07:46:29.201Z",
        "users": {
            "facebookId": "111111",
            "unread": 0
        },
    }, //And so on.
] 

But can I only get the objects after unwind where messages.userId !== users.facebookId

something like the following object directly from MongoDB when i fetch data

[
    {
        "_id": "5a44e6545818041cde24aac9",
        "messages": {
            "createdAt": "2017-12-23T07:46:29.201Z",
            "message": "Hii",
            "userId": "000000"
        },
        "createdAt": "2017-10-23T07:46:29.201Z",
        "users": {
            "facebookId": "111111",
            "unread": 0
        },
    },{
        "_id": "5a44e6545818041cde24aac9",
        "messages": {
            "createdAt": "2017-12-23T12:46:29.201Z",
            "message": "Bye gtg ttyl",
            "userId": "111111"
        },
        "createdAt": "2017-10-23T07:46:29.201Z",
        "users": {
            "facebookId": "0000000",
            "unread": 0
        }
    }, {
        "_id": "5a44e6545818041cde24aac9",
        "messages": {
            "createdAt": "2017-12-24T07:46:29.201Z",
            "message": "Bye Take Care",
            "userId": "000000"
        },
        "createdAt": "2017-10-23T07:46:29.201Z",
        "users": {
            "facebookId": "111111",
            "unread": 0
        }
    }
]

I tried this but the output is same :/

chats.aggregate( [ { $unwind : "$messages" },{ $unwind : "$users" },{$match:{ 'messages.userId' :{ $ne: '$users.facebookId'}}}]).exec(function(err, data) { res.send(data); });

2 Answers 2

2

As per MongoDB BOL $unwind Deconstructs an array field from the input documents to output a document for each element. Each output document is the input document with the value of the array field replaced by the element.

The $unwind stage has the following prototype form:

{ $unwind: <field path> }

To specify a field path, prefix the field name with a dollar sign $ and enclose in quotes.

Behaviors

$unwind has the following behaviors:
  1. If a value in the field specified by the field path is not an array, db.collection.aggregate() generates an error.
  2. If you specify a path for a field that does not exist in an input document, the pipeline ignores the input document and will not output documents for that input document.
  3. If the array holds an empty array ([]) in an input document, the pipeline ignores the input document and will not output documents for that input document.

For example

Consider an inventory with the following document:

> db.inventoty.insert({"_id" : 1, "item" : "ABC1", sizes: [ "S", "M", "L"] })
WriteResult({ "nInserted" : 1 })
> db.inventory.find().pretty()
> db.inventory.insert({"_id" : 1, "item" : "ABC1", sizes: [ "S", "M", "L"] })
WriteResult({ "nInserted" : 1 })
> db.inventory.find().pretty()
{ "_id" : 1, "item" : "ABC1", "sizes" : [ "S", "M", "L" ] }
> db.inventory.aggregate( [ { $unwind : "$sizes" } ] )
{ "_id" : 1, "item" : "ABC1", "sizes" : "S" }
{ "_id" : 1, "item" : "ABC1", "sizes" : "M" }
{ "_id" : 1, "item" : "ABC1", "sizes" : "L" }

Each document is identical to the input document except for the value of the sizes field which now holds a value from the original sizes array.

2
  • yes but I want to modify that i get it as i want it Commented Dec 31, 2017 at 8:03
  • @Sandeep Ranjan, what you want to modify in the output of result? Commented Dec 31, 2017 at 8:18
1

This solved it.. :)

  chats.aggregate([{
                $unwind: '$users'
            }, {
                $project: {
                    messages: 1,
                    users: 1,
                    'messages': {
                        $filter: {
                            input: '$messages',
                            as: 'item',
                            cond: {
                                $ne: ['$$item.userId', '$users.facebookId']
                            }
                        }
                    }
                }
            },{ $unwind : "$messages" }
        ])
2
  • 1
    Along with the code try to write down bit more for better clarafication. What actually you are going to do that? Commented Dec 31, 2017 at 8:19
  • 1
    As '$unwind',Deconstructs an array field from the input documents to output a document for each element. Each output document replaces the array with an element value. For each input document, outputs n documents where n is the number of array elements and can be zero for an empty array. Commented Dec 31, 2017 at 8:22

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.