Searching user by roles


#1

is it possible to filter in my collection of users, the search of only users according to the role?

something like this:

var user = Meteor.users.find({_id: this.userId},{fields: { 'roles': 'free' }});

for (var k = 0; k < user.length; k++) {

//do something only if you are free.
//I want to avoid having to ask all registered users if it is free
  if (Roles.userIsInRole(t[k]._id, 'free')){
   }

}

#2

var userId; // pass your user id
var list=Meteor.users.find({roles:“free”}}).fetch();
for sinle user use can use
var user=Meteor.users.findOne({$and:[{_id:userId},{roles:“free”}]});
list will contain all the users where roels=free


#3

hi thanks,
does not work as you indicate I need to perform the search from the server to all registered users, therefore I do not handle a userId as such, everything happens backwards for users through cronJobs I analyze if we say 48 hours passed then you are from role free you can do this again.

as I have it works I just wanted to optimize the search for only free users do not have to go in the search for the users premiun


#4

can you share a more complete snippet of how you’re doing it right now? You need to create a list already filtered. If you search all the users and then filter, then there’s your problem.


#5

@fermuch hi , thanks for reply.

I just need the users who are registered with the role free then I need them according to the difference obtained from the subtraction if the two days went by then I command to reset everything again.

timer1: function(timer) {
  try {
    var t = Meteor.users.find({ id: this.userId }).fetch();
    //var p = Meteor.users.find({_id: this.userId},{fields: { 'roles': free }});
    //var list = Meteor.users.find({$and:[{ id:this.userId},{roles:  'free'}]}).fetch();
    for (var k = 0; k < t.length; k++) {
      var result = Invitation.find({sender_id: t[k]._id}).fetch();
        var data = ControlInvitaciones.find({}).fetch();
        var data_aceptadas = data[0].aceptadas;
        var data_enviadas = data[0].enviadas;
        var tiempo1 = data[0].tiempo;
        var tiempo2 = data[0].tiempo2;
        var tzone = t[k].profile.timezone;
        var time_invitaciones = t[k].profile.send_invitations_time;
        var roles = t[k].roles;
        var time_invitaciones_aceptadas = t[k].profile.AcceptCount_timer;
        var date1 = momentT.tz(timer, tzone).format('YYYY-MM-DD HH:mm');
        var date2 = moment(time_invitaciones, "YYYY-MM-DD HH:mm");
        var resta = Math.abs(date2.diff(date1, 'days'));
        var date3 = moment(time_invitaciones_aceptadas, "YYYY-MM-DD HH:mm");
        var restaAceptar = Math.abs(date3.diff(date1, 'days'));

      if (Roles.userIsInRole(t[k]._id, 'free')){
      if (resta !== NaN){
        if (resta >= 2 && t[k].profile.send_invitations_check == true) {
          console.log("Tiempos restablecidos")
          Meteor.users.update({_id : t[k]._id},{$set : {'profile.send_invitations_time' : "" ,'profile.send_invitations' : 0,'profile.send_invitations_check' : false}});
          var message = "Send invitations have been reset";
          var type = "timer";
          Meteor.call("resetTimerPush", t[k]._id,message,type, function(error, result){
            if(error){
              console.log("error", error);
            }
          });
      }
      }
}

    }
  } catch (e) {
      console.log("console error timer1",e)
  }
},

#6

That sounds like something you might be able to do with the aggregation pipeline, or with MapReduce.

If you dont want to rewrite everything, you’d need to omit this line:

if (Roles.userIsInRole(t[k]._id, 'free')){

And maybe use updateMany for this line:

Meteor.users.update({_id : t[k]._id},{$set : {'profile.send_invitations_time' : "" ,'profile.send_invitations' : 0,'profile.send_invitations_check' : false}});

Since those two contact the database, they’ll make your loop slower.


One thing I don’t understand: why are you looping over t? Is there a case where two users have the same id?


#7

Ok I’ll check the documentation that you passed me. Any questions about that I ask you.

No, I’m doing the consultation one by one. so I have the for looping over t, as I know that in t I have all the users what I do is for the user in t [0]. for the user in t [1] something very rudimentary so I am asked to see if there was any way to perform the search optimization.


#8

I did not test this code, but it should work. I hope the code is self explanatory.
The try/catch block is unnecesary and a bad practice. If you come from java, that black is unnecesary here. Just let Meteor handle errors, if there is one. None of the operations used (find(), findOne()) throw errors if they fail, they just return an empty array for find and null for findOne, so the only catch you’re doing is of your own code, which is easier to spot if Meteor warns you about the error.

timer: function(timer) {
  try {
    var sender = Meteor.users.findOne({
      // search by the user ID
      _id: this.userId,
      // but ONLY if he has the "free" role
      roles: 'free'
    });

    if (!sender) {
      // if we didn't find a sender, return
      return;
    }

    var result = Invitation.find({sender_id: sender._id}).fetch();
    var data = ControlInvitaciones.find({}).fetch();
    var data_aceptadas = data[0].aceptadas;
    var data_enviadas = data[0].enviadas;
    var tiempo1 = data[0].tiempo;
    var tiempo2 = data[0].tiempo2;
    var tzone = sender.profile.timezone;
    var time_invitaciones = sender.profile.send_invitations_time;
    var roles = sender.roles;
    var time_invitaciones_aceptadas = sender.profile.AcceptCount_timer;
    var date1 = momentT.tz(timer, tzone).format('YYYY-MM-DD HH:mm');
    var date2 = moment(time_invitaciones, "YYYY-MM-DD HH:mm");
    var resta = Math.abs(date2.diff(date1, 'days'));
    var date3 = moment(time_invitaciones_aceptadas, "YYYY-MM-DD HH:mm");
    var restaAceptar = Math.abs(date3.diff(date1, 'days'));

    // the next check is unnecesary, since we already checked if the user is in the free role
    // before.
    // if (Roles.userIsInRole(sender._id, 'free')){
    if (resta !== NaN){
      if (resta >= 2 && sender.profile.send_invitations_check == true) {
        console.log("Tiempos restablecidos")
        Meteor.users.update({_id : sender._id},{$set : {'profile.send_invitations_time' : "" ,'profile.send_invitations' : 0,'profile.send_invitations_check' : false}});
        var message = "Send invitations have been reset";
        var type = "timer";
        Meteor.call("resetTimerPush", sender._id,message,type, function(error, result){
          if(error){
            console.log("error", error);
          }
        });
      }
    }
  } catch (e) {
      console.log("console error timer1",e)
  }
}

#9

thank for helpme, if only I had an error, for what I need the most that is about the Aggregation Pipeline or Map-Reduce to perform a search all free users. I will document a little more about it.