Access meteor user email - meteor-accounts

typical schema:
emails: {
type: Array,
optional: true
},
"emails.$": {
type: Object
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email
},
"emails.$.verified": {
type: Boolean
},
I have a form that edits the meteor.user emails field . I want to access this field after the form is submitted to a method but having difficulty doing so.
somemethod: function(doc){
//i have tried but i get undefined
console.log(doc.emails[0].address)
}
how do i get this? Thank you.

Related

Populating multiple fields with a pre "find" middleware

I am trying to specify the fields that should always be populated for the user document in a pre "find" middleware, like this:
userSchema.pre(/^find/, function (next) {
this.populate("followers following"); next();
});
Here is the user schema:
const userSchema = new mongoose.Schema<IUser>(
{
firstName: {
type: String,
required: [true, "You must provide your first name."],
},
lastName: {
type: String,
required: [true, "You must provide your last name."],
},
profilePic: {
type: String,
},
email: {
type: String,
required: [true, "You must provide an email."],
unique: true,
},
password: {
type: String,
required: [true, "You must provide a password."],
},
isVerified: {
type: Boolean,
default: false,
},
verificationToken: {
type: String,
},
role: {
type: String,
enum: ["user", "admin"],
default: "user",
},
followers: [{ type: mongoose.Schema.Types.ObjectId, ref: "User" }],
following: [{ type: mongoose.Schema.Types.ObjectId, ref: "User" }],
},
{
timestamps: true,
}
);
But when I send the request it's just stuck not sending any response.
It works just fine when I only populate one field, either 'followers' or 'following', but together it won't work.
I tried a bunch of different ways, but nothing seems to work.
If anyone can help I would be very thankful!
#1 Have you tried to seperate them ?
userSchema.pre('find', function (next) {
this.populate("followers").populate("following");
next();
});
#2 Or with an array of paths
userSchema.pre('find', function (next) {
this.populate(['followers', 'following']);
next();
});
As documentation states here and here:
The Document#populate() method does not support chaining. You need to
call populate() multiple times, or with an array of paths, to populate
multiple paths.
#3 Or to use deep-populate if you're populating across multiple levels as documented here:
I've got the working solution.
The issue is that if the populate() method in the middleware has more than one field, it calls the middleware for each field and it triggers infinite recursion, which makes the request hanging.
The workaround is a bit weird, but pretty straight forward. We have to add the _recursed option so the middleware knows to avoid populating recursively.
userSchema.pre(/^find/, function (next) {
if (this.options._recursed) {
return next();
}
this.populate({ path: "followers following", options: { _recursed: true } });
next();
});

How to give iDs to dynamic fields in React-Redux?

I created a simple dynamic fields in React-Redux with a plus button to add as many field as I want (hobbies) of an already existing form. I'm using mongodb as a database and so I have this error that tells me that my fields/data don't have iDs.
so how can I generate iDs for my data?
this below is my model with featherJs. as you can see this is how I added my hobbies array in the existing model called myService. I can see that my hobbies are created in mongo (using Robo 3T) which is great but i'm having difficulty reusing them (hobbies) in an other component in Redux. I'm not sure if I should give IDs to this fields or create a new service just for them. I never coded something in backend so I'm confused. what's the rule for this kind of situations.
Any other suggestions would be helpful.
warning in Redux: Each child in a list should have a unique "key" prop.
error in api : Cast to ObjectId failed for value at path "_id" for model "
const { Schema } = mongooseClient;
const myService = new Schema({
type: { type: String, enum: VALID_TYPES, required: true },
user: {
type: mongooseClient.Schema.Types.ObjectId,
ref: 'user',
required: true
},
comment: String,
hobbies: [{
type: mongooseClient.Schema.Types.ObjectId,
ref: 'hobbies',
default: [],
required: false }],
date: {
begin: { type: Date, default: Date.now },
current: { type: Date, default: Date.now },
end: { type: Date, required: true },
},
}, {
timestamps: true
});
return mongooseClient.model('myService', myService);
};

How can I use partialFilterExpression on a mongoose model

I have created a mongoose model that has an email field. I want it to be unique if a value is provided by a user but I want it to be empty is a user has not provided any value. I have found a good mongodb reference here: https://docs.mongodb.com/manual/core/index-partial/#partial-index-with-unique-constraints that could work but I don't know how to make it work on mongoose
This is how the field looks like right now
email: {
type: String,
index: true,
unique: true
}
If I leave it the way it is, I cant create multiple documents with an empty/null email field
In the email path level, you can use only:
email: {
type: String
}
And in the schema level use:
SchemaName.index({ email: 1 }, {
unique: true,
partialFilterExpression: {
'email': { $exists: true, $gt: '' }
}
});
This way the unique constraint is applied only if email exists and is not an empty string
You can have something like :
email: {
type: String,
index: {
unique: true,
partialFilterExpression: { email: { $type: 'string' } },
},
default : null
}
but do read below link, before you actually implement it, as defaults seems to work only on new document inserts :-
Mongoose v5.6.9 Documentation
You can use sparse
email: {
type: String,
unique: true,
sparse: true
}
That way if you dont't send the email field at all mongo will not add automatically null value for the field. It will just skip it.

Updating specific attribute for a specific user

I am trying to update a specific attribute for a specific user in mongodb. I am having trouble understanding the nested-ness. Any help would be appreciated.
My specific problem is that I want to update a the activeID for a specific _cID that is specific to a User(a user can have many _cID's hence the array type in settings.
Here is the server call that I currently have
'updateActive' : function (p_id, c_id) {
Collections.Users.update({_id: Meteor.userId(), _cID: c_id},{$set: {'settings.$.activeID': p_id}});
}
and the schema
Schemas.CSettings = new SimpleSchema({
_id: {
type: String
},
_cID: {
type: String
},
activeID: {
type: String,
optional: true
}
});
Schemas.User = new SimpleSchema({
_id: {
type: String
},
createdAt: {
type: Date
},
profile: {
type: Schemas.UserProfile
},
settings: {
type: [Schemas.CSettings],
optional: true
}
});

Populate query with match returns null

I have three schemas, that need them to be separated and I can't use subdocuments. The important one is this
export var TestSchema = new mongoose.Schema({
hash: { type: String, index: { unique: true }, default: common.randomHash },
date: { type: Date, default: Date.now },
result: { type: Object },
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
data: { type: Object },
finished: Date,
lang: { type: String, default: 'pt' },
benchmark: { type: String, required: true },
order: { type: mongoose.Schema.Types.ObjectId, ref: 'Transaction' },
/* TODO: remove */
name: { type: String }
});
I have a query that does the populate (it's actually a pagination helper, but I'm cutting to the chase):
TestModel.find({hide: {$ne: true}, user: id}).populate({
path: 'user',
match: {$or: [
{email: new RegExp(search, i)},
{name: new RegExp(search, i)},
{empresa: new RegExp(search, i)},
]}
}).exec().then(/*...*/)
when populate.match doesn't find anything, it sets the user to null. I tried setting the find({'user':{$ne: null}}) but it ignores it. (I guess the populate happen after the find call, maybe that's the reason).
Is there any way I can filter it in the database layer instead having to rely on iterating of the results, check for null then filter out?
This answer on GitHub clarifies that it is not possible with populate, due to how MongoDB works. However, you should be able to do it with $lookup.