Meteor Querying other users by email - mongodb

I'm trying to query users by emails with the following command
Meteor.users.findOne({'emails.address': 'me#example.com'});
It works in the mongo shell but it returns undefined in Meteor.
Any ideas?
UPDATE
Turned out that I'm not able to query other users. The same query works when I query the logged in user email.
So the question now how can I query on all the users?

By default, Meteor only publishes the logged in user and you can, as you mention, run queries against that user. In order to access the other users you have to publish them on the server:
Meteor.publish("allUsers", function () {
return Meteor.users.find({});
});
And subscribe to them on the client:
Meteor.subscribe('allUsers');
Also keep in mind that you might not want to publish all the fields so you can specify what fields you like to publish/not publish:
return Meteor.users.find({},
{
// specific fields to return
'profile.email': 1,
'profile.name': 1,
'profile.createdAt': 1
});
Once you have published the collection, you can run queries and access information for all the users.

This may be helpful:
var text = "me#example.com";
Meteor.users.findOne({'emails.address': {$regex:text,$options:'i'}});
Also see Advance Queries

First you need to publish the users as mentioned above answer and run the following command
Meteor.users.find({"emails": "me#example.com"}).fetch()
OR
Meteor.users.find({"emails.0": "me#example.com"}).fetch()

Related

MongoDB - Stitch: Can't make custom user data to appear in userObject.customData

When I log with a user the userObject contains empty customData object despite saving a document in custom data collection pointing to the app user.
I tried to follow the documentation:
In the Users section of Mongo Stitch panel I enabled custom data. I chose database, collection (users) and stated User ID Field to be userId. Then I deployed changes.
I have a created and confirmed user.
I copied the user's _id and from shell (from admin account and context of the relevant db) I ran command db.users.insertOne({userId: ObjectId('copied_id'), description: "something"}). It was acknowledged and when I query the collection I see relevant document with userId field having correct ObjectId() value.
I even tried to set read rights to the users collection.
Nonetheless, if I log in with my user, customData object is empty. What can be the cause of this?
same issue here... pebcak :/
I fixed it by setting userId as String, not ObjectId.
Hoping it's not too late ;)

How to insert new document only if it doesn't already exist in MongoDB

I have a collection of users with the following schema:
{
_id:ObjectId("123...."),
name:"user_name",
field1:"field1 value",
field2:"field2 value",
etc...
}
The users are looked up by the user.name, which must be unique. When a new user is added, I first perform a search and if no such user is found, I add the new user document to the collection. The operations of searching for the user and adding a new user, if not found, are not atomic, so it's possible, when multiple application servers are connect to the DB server, for two add_user requests to be received at the same time with the same user name, resulting in no such user being found for both add_user requests, which in turn results with two documents having the same "user.name". In fact this happened (due to a bug on the client) with just a single app server running NodeJS and using Async library.
I was thinking of using findAndModify, but that doesn't work, since I'm not simply updating a field (that exists or doesn't exist) of a document that already exists and can use upsert, but want to insert a new document only if the search criteria fails. I can't make the query to be not equal to "user.name", since it will find other users.
First of all, you should maintain a unique index on the name field of the users collection. This can be specified in the schema if you are using Mongoose or by using the statement:
collection.ensureIndex('name', {unique: true}, callback);
This will make sure that the name field remains unique and will solve the problem of concurrent requests as you have specified in your question. You do not require searching when this index is set.

Mongodb Aggregate: Nested totals

I am trying to generate a report from our mongo db that tallies up the unique visits by country code per referral site. I'd like to use aggregation as I've heard it is quite fast and performance here is an issue.
We have an account db that has a country code and last referral site associated with each account.
{
account:"user123",
CountryCode:"CA",
ReferalSite:"Google",
lastLogin:"someisodate"
}
Conceptually, I can write the javascript in a few minutes.
For each unique vistor in accounts db;
visits[vistor.country_code][vistor.refferal_site]+= 1;
Is this query possible with a db.accounts.aggregate()? Or is a map/reduce the better way to go about this.
Thanks in advance,
You can run two groups one after another :
db.collection.aggregate([
{$group:{_id:{account:'$account', CountryCode:'$CouintryCode', ReferalSite:'$ReferalSite'}}, {number:1}},
{$group:{_id:{CountryCode:'$_id.CountryCode', ReferalSite:'$_id.ReferalSite'}}, {number:{$sum:'$number'}}}])

How to query username from userId in a collection in Meteor?

I am trying to implement a basic search bar functionality in my app.
I have a bunch of articles, and everyone has an owner. This is specified by the userId in the user parameter of each article.
Right now I can search for keywords within the article, the title, and the date. However I want to be able to query for the username of the author of the article, but I only have the userId available to me...
var keyword = Session.get("search-query");
var query = new RegExp( keyword, 'i' );
var results = Articles.find( { $or: [{'user': query}, // this is only searching userId of the author!
{'title': query},
{'articleText': query},
{'datetime': query}] } );
return {results: results};
I'm not sure how to do this...
Welcome to non-relational databases! You're coming from an RDBMS environment so you expect joins. There are none. Store the username in the article it belongs to, then yes, if a user change their username, you'll need to loop through the collection and update the username where the _id matches.
Please look here for mongo strategies (this isn't Meteor-specific at all): http://docs.mongodb.org/manual/core/data-modeling/
PS: If you get eye haemorrhaging whenever you look at your schema-which-actually-really-isn't-one, you can still give https://github.com/erundook/meteor-publish-with-relations a go - but note that under the hood it's going to get even 'worse' (have a look at your mongo opslog). Publish with relations is only there for convenience and ease of programming, not performance.
Good luck!
So I guess you'd have to either save the username as well as it's own field (or put both id and username in a user object), or search the Users collection for valid usernames, and when you found one use its id to search the Articles DB.
The first suggestion would probably be way more efficient I guess.
That's pretty easy, assuming you're doing the search on the server which has access to all the users:
var username = Meteor.users.findOne(userId).username;

Updating Embedded Array And Objects In Mongo

In Mongo I have a collection of post and each post has comments that are embed with a user id, user name and user email.
- post
- comments
- user_id name email
I was wondering how can I update the all the emails that are associated with a certain id?
Currently, you would have to retrieve comments first, and then update emails.
Depending on which client you use, here is a mongoid example:
comments = post.comments
comments.update_attributes(:email => "a#b.c")
Also there is already a "Use positional operator to update all items in an array" JIRA that, once implemented, will allow you to do it in one shot.
Have you tried the $ positional operator, its the only way to update the matching sub(embedded docs) docs.