0

I have a post document like so

author: '828287',
content: 'xyz',
time: 88273622324

And my user document looks like

id: '345678',
name: 'John McClane',
blocked: [{
   user: '123214',
   time: 88273626362
},{
   user: '345654',
   time: 88273698678
},{
   user: '554568',
   time: 88273658858
}],
created: 127381283

How can I select all of the posts that are by authors whose user id is not in my blocked field?

EDIT: Additionally, how can I select all of the posts by authors who are blocked, but only if the time of the post is prior to the time of the block? This means blocking a user will only block future posts and existings posts will not be affected.

3
  • 1
    Can you confirm whether the author field in the post schema is string or int? Commented Dec 28, 2015 at 19:13
  • Is the author field of the post document supposed to match with the id field of the user document? What is the significance of blocked[i].user? Commented Dec 28, 2015 at 19:13
  • author field is String. Yes, the author field of the post document is equal to the id field of the user who posted it. blocked is an array of users whose posts have been blocked and therefore, we do not want to select them. Commented Dec 28, 2015 at 21:29

1 Answer 1

2

This should work

map the user's blocked property (I'm assuming you can parse that to an array):

var blockedUsers = user.blocked.map(function (b) {
    return b.user; //if b.user is a number and author is a string then use return b.user.toString() instead
});

query the db...

db.posts.find({author: {$nin: blockedUsers}});

EDIT

Try this one out for your edit

var condition = user.blocked.map(function (b) {
    var aux = { $and: [ { author: b.user }, { time: {$lt: b.time} } ] };
    return aux; 
});

var blockedUsers = user.blocked.map(function (b) {
    return b.user; //if b.user is a number and author is a string then use return b.user.toString() instead
});

condition.push({ author: {$nin: blockedUsers }});

db.posts.find({$or: condition });

The variable condition ends up looking like this

[
    {$and: [ {author: "123214"}, {time: { $lt: 88273626362 } } ] },
    {$and: [ {author: "345654"}, {time: { $lt: 88273698678 } } ] },
    {$and: [ {author: "554568"}, {time: { $lt: 88273658858 } } ] },
    {author: {$nin: ["123214", "345654", "554568"] }}
]

That should help you understand the query

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

5 Comments

blockedUsers is an array of integers and the author field in the post collection (according to the OP provided schema) is of string type hence the query won't find a match.
I assume that was just an example.. but if that is the case then I would advice to normalise the type in both places. In any case I'll edit the answer to include that scenario
This is correct for the question as I had asked it, but this solution does not lend itself well to solving my next step that I did not mention. I have updated the post with the second part.
@JacobPariseau It's considered a bad habit here on SO to change questions after someone has answered. I would strongly recommend if this answered your initial question to consider marking the answer as accepted and to suggest the new direction might be better handled as a new question. For more meta details, refer to Exit strategies for “chameleon questions”.
@JacobPariseau check my edit for your new requirements

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.