Reputation: 536
I'm trying to do a rather unique query that I can't seem to google myself out of. This is also my first real Meteor app. I'm trying to ultimately return all listings that the user has not yet 'liked' or 'disliked'.
Basically any user with a foo listing can view all bar listings and choose like or dislike to eventually see if there is a mutual match. If they like the listing, it pushes the liked listing's _id to their own listings likes array (same with dislikes). In my ex. below, listing id 'a' likes both listings 'b' & 'd' but has not seen c yet.
The matching part is working, however I don't want to keep showing them listings they've already seen.
Currently the collection and query looks something like this (distilled down for ex.). Which currently looks very inefficient and cumbersome:
userLikes = listings.findOne({ userId: Meteor.userId() }).likes
userDisikes = listings.findOne({ userId: Meteor.userId() }).dislikes
listings.find({ type: 'bar',
likes: {$nin: userLikes }, dislikes: {$nin: userDislikes} })
listings collection:
{
_id: 'a',
userId: 'someuserid',
type: 'foo',
likes: ['b','d'],
dislikes: []
},
{
_id: 'b',
userId: 'someuserid',
type: 'bar',
likes: ['a'],
dislikes: []
},
{
_id: 'c',
userId: 'someuserid',
type: 'bar',
likes: [],
dislikes: []
},
{
_id: 'd',
userId: 'someuserid',
type: 'bar',
likes: [],
dislikes: []
}
In retrospect (while typing this), i'm thinking my original approach was inverted. Should I just store the likee's listing id on the liked listing? e.g. Pushing the user's _id
to the liked listing's wasLikedBy
array or something so that you could query like this instead:
listings.find({type:'bar', {wasLikedBy: {$ne: 'a'}} })
Any advice on how to tackle this is much appreciated, I'm also new to databases so i'm trying to soak it all in as much as possible.
Upvotes: 0
Views: 1961
Reputation: 19544
There are three basic possibilities when you design a many-to-many relationship. Either you store an array on one side, on the other side, or create a join table. Each choice has its advantages and disadvantages and which one you use depends on what you find easy or more appropriate for the model. You should be able to do all things easily regardless of the choice.
In this case, you should get more accustomed with how Mongo treats arrays. Basically, it applies the condition to all elements of the array, so if you use $ne
on an array parameter, you get results that doesn't contain the given elements in the array.
Long story short, here's your code:
listings.find({
type: 'bar',
likes: {$ne: Meteor.userId()},
dislikes: {$ne: Meteor.userId()},
});
Upvotes: 1