0

I am using Meteor, and I want to get a list of contacts: - each contacts has an id, - I want to search the DB for all the user to see if I find matching IDs, - if I find them I need to: a) update my contact[i] b) update the found ID with my personal ID

The problem with this is that I don't manage [so far] to do this operation with Mongo.

Full post is here https://forums.meteor.com/t/connecting-users-mongo-strategy/4132

Code here:

for (var i = 0;i < contacts.length; i++) {
            Meteor.users.find({"profile.phone": contacts[i].phone}).forEach(function(friend){
                console.log('We found a friend', friend);
                contacts[i].appActive = true;
                contacts[i].appId = friend._id;

                Meteor.users.update({_id: friend._id}, { $addToSet: { "profile.friends": Meteor.userId() }});
            });
        }

The logic is sound, the problem is with HOW I understand Mongo [poorly], I'm guessing the queries are async, I'm trying to create a cursor with find on the server side but I'm stuck.

Any pointer are appreciated. Thanks!

1
  • Please post all relevant codes and resources in the question itself. If for some reason the Meteor website dies (or is deviated by a larger mass), your question will lack critical data. Here, we need two things: Your code and your document structure. Commented May 11, 2015 at 9:47

2 Answers 2

2

Try to limit your database calls. If I understand your use, you need one call to fetch friend records and a second call to update all those records with the current userId.

The db calls within the loop over contacts can be avoided by creating separate array of phone numbers.

var phones = _.pluck(contacts, 'phone');
Meteor.users.find({'profile.phone':{$in: phones}}).forEach( function (friend) {
  var ii = phones.indexOf( friend.profile.phone );
  contacts[ii].appActive = true;
  contacts[ii].appId = friend._id;
});

Meteor.users.update(
  {'profile.phone':{$in: phones}}, 
  {$addToSet: {'profile.friends': Meteor.userId()}},
  {multi: true}  // all matching records receive update
);
Sign up to request clarification or add additional context in comments.

1 Comment

Yeah, the logic was mostly sound, but your input here is even better. The problem I had [of course] was that I used to process and hash the phone numbers, I processed them ONLY for the contacts array, not the user's actual phone (facepalm), took me a while to get that, I got the crazy idea to start comparing the hashesm then I found that dumb TYPO. :)
1

Your code does not look too bad in my opinion. (as long as it's server side) And no, in Meteor, most collection methods are not asynchronous! Just use Collection.findOne and it should work:

for (var i = 0;i < contacts.length; i++) {
           var friend = Meteor.users.findOne({"profile.phone": contacts[i].phone});
                console.log('We found a friend', friend);
                contacts[i].appActive = true;
                contacts[i].appId = friend._id;

                Meteor.users.update({_id: friend._id}, { $addToSet: { "profile.friends": Meteor.userId() }});
        }

If you do want to get multiple users with the same phone number (I thought it was weird, so I assumed phone numbers were unique), you will need to use find().fetch() before your forEach:

for (var i = 0;i < contacts.length; i++) {
            Meteor.users.find({"profile.phone": contacts[i].phone}).fetch().forEach(function(friend){
                console.log('We found a friend', friend);
                contacts[i].appActive = true;
                contacts[i].appId = friend._id;

                Meteor.users.update({_id: friend._id}, { $addToSet: { "profile.friends": Meteor.userId() }});
            });
        }

If for some reason you want to do this client-side, you will first need to publish your users on server side, and subscribe to your publication on client side. Here's a nice article about it from Discover Meteor.

1 Comment

Thanks! Yes, the code is server side in a method. I found my problem, commented in the above answer.

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.