0

Based on the logged in user his/her preferences I want to create a collection and display in a view.

I'm in no way experienced with mongodb and now i'm ending up with this huge if/else statement and it's already slow (with 7 users in DB). But afaik it does give me the right results.

Meteor.publish('listprofiles', function () {

    if ( ! this.userId ) return [];  

    var user =  Meteor.users.findOne({ _id: this.userId }, {
                    fields : {
                        'profile.gender': 1,
                        'profile.preference': 1
                    }
                }),
        query;

    user.gender = user.profile.gender;
    user.preference = user.profile.preference;

    if (user.gender === 'man') {
        if (user.preference === 'straight') {
            query = {
                        $and: [
                            { 'profile.gender': 'woman' },
                            { 
                                $or : [{ 'profile.preference' : 'straight' }, 
                                       { 'profile.preference' : 'bi' }] 
                            }
                        ]
                    };

        } else if (user.preference === 'gay') {
            query = {
                        $and: [
                            { 'profile.gender': 'man' },
                            { 
                                $or : [{ 'profile.preference' : 'gay' }, 
                                       { 'profile.preference' : 'bi' }] 
                            },
                        ]
                    };

        } else if (user.preference === 'bi') {

            query = {
                    $or: [
                            {
                                $and: [
                                    { 'profile.gender': 'man' },
                                    { 
                                        $or : [{ 'profile.preference' : 'gay' }, 
                                               { 'profile.preference' : 'bi' }] 
                                    },
                                ]
                            },
                            {
                                $and: [
                                    { 'profile.gender': 'woman' },
                                    { 
                                        $or : [{ 'profile.preference' : 'straight' }, 
                                               { 'profile.preference' : 'bi' }] 
                                    }
                                ]
                            }
                        ]
                    };
        }

The queries work, I tested them, but I'm unsure how to fit them dynamically. My guess is that query also shouldn't be an object, but I'm not sure how to create a valid variable..

var dbFindQuery = Meteor.users.find({ 
            'profile.invisible': false,
            queryShouldBeHereButObviouslyThisDoesNotWork
        }, {
            fields : {
                'profile.name': 1,
                'profile.city': 1,
                'profile.country': 1,
                'profile.gender': 1,
                'profile.preference': 1,
                'profile.story': 1
            }
        });
        console.log(dbFindQuery.fetch());
        return dbFindQuery;

anyone can give me a pointer in the right direction?

1 Answer 1

1

You can certainly factor out the common query objects. Here's one way to approach it:

Meteor.publish('listprofiles', function() {
  if (!this.userId)
    return [];

  var user = Meteor.users.findOne(this.userId);

  var gender = user.profile.gender;
  var preference = user.profile.preference;

  var straightOrBiWoman = {
    'profile.gender': 'woman',
    'profile.preference': {$in: ['straight', 'bi']}
  };

  var gayOrBiMan = {
    'profile.gender': 'man',
    'profile.preference': {$in: ['gay', 'bi']}
  };

  var query = {};

  if (gender === 'man') {
    switch (preference) {
      case 'straight':
        query = straightOrBiWoman;
        break;
      case 'gay':
        query = gayOrBiMan;
        break;
      default:
        query = {$or: [gayOrBiMan, straightOrBiWoman]};
    }
  }

  query['profile.invisible'] = false;

  return Meteor.users.find(query, {fields: {profile: 1}});
});

Here we are reusing straightOrBiWoman and gayOrBiMan based on the user's gender and preference. Note that I used the $in operator to simplify the query. I'd also suggest that you not specify 2nd-level fields in your fields modifier for reasons explained here. Finally, I'd recommend testing this code, as I may have missed something in the logic when rewriting it. Hopefully this example will help guide you in the right direction.

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

4 Comments

hey @DavidW thanks so much for taking the time to reply to one of my questions again! I get an error from thequery[{'profile.invisible': false}]; line though. In the console it logs the (I believe) whole mongo object back to me. So I'm not sure what's going no as the message is not clear to me at all. starts with: { _mongo: { _observeMultiplexe....... Also I thought the fields modifier was required because we're trying to get data from the Meteor.users collection which is 'secure' by default. Or did I misunderstood this?
Sorry I had a couple of typos in the answer; give it another try. Also note that the gender === 'woman' case isn't written, so you'll need to add that or all profiles will be published in that case. It's very important to have a fields modifier when publishing users. I'm saying you don't want to specify fields that are 2-levels deep. e.g. specify "profile", don't specify "profile.gender".
ahhh, awesome! that saves a lot of typing regarding the fields modifier. I added a guard if (!user || !gender || !preference) return; right after declaring those variables. Just wanted to say you taught me that in a previous question (not sure if its required). The huge log in console wasn't helping at all though. What do you do in such a case? thanks so much again!
oh by the way when I log the return statement it still gives me a giant mongo object, but I expected just the users. The query does work though!

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.