1

I have a collection like this:

{
_id : 123,
username : "xy",
comments : [
    {
        text : "hi",
        postdate : 123456789
    },
    {
        text : "hi1",
        postdate : 555555555
    },
    {
        text : "hi2",
        postdate : 666666666
    },
    {
        text : "hi3",
        postdate : 987654321
    }

]}

Now I want only the comments that have postdate 555555555 or higher and 987654321 or lower. I have this query, but it doesn't work:

db.post.aggregate([
{$match : {$and : [ 
{"_id": ObjectId("123")},
{"comments.posttime" : {$lte : 987654321}},
{"comments.posttime" : {$gte : 555555555}}
]}}
,{$unwind: "$comments"}]).pretty();

But when I try this it gets me all of the array elements. How should this be done?

Thank you!

1

2 Answers 2

2

Use $redact to Restricts the contents of the document,

                db.an.aggregate([{
        $redact: {
            "$cond": [{
                $and: [{
                    "$gte": [{
                            "$ifNull": ["$postdate", 555555555]
                        },
                        555555555
                    ]
                }, {
                    "$lte": [{
                            "$ifNull": ["$postdate", 987654321]
                        },
                        987654321
                    ]
                }]
            }, "$$DESCEND", "$$PRUNE"]
        }
    }]).pretty()
Sign up to request clarification or add additional context in comments.

4 Comments

thank you for the answer! But it doesn't work. If the $gte is 555555555 I don't get any element. If I set this to 0 and the $lte from 987654321 to 666666666 I get the full stack.
For me it worked with your data, $gte 0 and $lte 666666666,
db.an.aggregate([{ $redact: { "$cond": [{ $and: [{ "$gte": [{"$ifNull":["$postdate", 0] }, 0 ] }, { "$lte": [{"$ifNull":["$postdate",666666666]}, 666666666 ] }] }, "$$DESCEND", "$$PRUNE"] } }]).pretty()
Ahh, yes! I made a dumb mistake. Thank you, it works!
0

you have to unwind the comments first and then do the match. so that comments array will be flattened and match condition can filter it properly.

[{$unwind: "$comments"},{$match : {$and : [ 
{"_id": ObjectId("123")},
{"comments.posttime" : {$lte : 987654321}},
{"comments.posttime" : {$gte : 555555555}}
]}}]

this will give one row for each comment, if you want the matching comments inside the array, use aggregate on _id and $push the 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.