Meteor - insert array of objects - javascript

I have this Schema (using meteor-collection2):
Settings = new Mongo.Collection("settings");
var Schema = {};
Schema.Settings = new SimpleSchema({
user_id: {
type: String,
optional: false
},
settings_firm_name: {
type: String,
optional: false
},
settings_firm_primary_branch: {
type: String,
optional: false
},
settings_firm_employees_num: {
type: Number,
optional: false,
min:1
},
settings_firm_address: {
type: String,
optional: false,
},
settings_firm_email: {
type: String,
regEx: SimpleSchema.RegEx.Email,
optional: false,
},
settings_firm_web_page: {
type: String,
optional: false,
},
settings_firm_contact_phone: {
type: String,
optional: false,
},
settings_firm_fax: {
type: String,
optional: false,
},
settings_firm_social: {
type: [Object],
optional: false,
},
"firm_social.$.name": {
type: String
},
"firm_social.$.link": {
type: String,
regEx:SimpleSchema.RegEx.Url
}
});
I want to add to my database data that is validated by this schema. settings_firm_social is array of object. That objects are created from three different input fields where each object have name and link fields. How can I insert that document in my database? I simply try with:
Settings.insert(settings, function(error,result){
if(error){console.log(error)}
});
But my array then is populated with three empty objects ({}).
EDIT
When I log settings object that I pass to Meteor method befor insert:
I20150627-00:29:36.523(2)? Server log
I20150627-00:29:36.543(2)? { settings_firm_name: 'Test',
I20150627-00:29:36.543(2)? settings_firm_primary_branch: 'test',
I20150627-00:29:36.543(2)? settings_firm_employees_num: '200',
I20150627-00:29:36.543(2)? settings_firm_address: 'Test',
I20150627-00:29:36.544(2)? settings_firm_contact_phone: '12345',
I20150627-00:29:36.544(2)? settings_firm_fax: '123445',
I20150627-00:29:36.544(2)? settings_firm_web_page: 'http://localhost:3000/settings/ZQwjxYzBuSfodxHvF',
I20150627-00:29:36.544(2)? settings_firm_email: 'test#hotmail.com',
I20150627-00:29:36.544(2)? settings_firm_social:
I20150627-00:29:36.545(2)? [ { name: 'Facebook',
I20150627-00:29:36.545(2)? link: 'http://localhost:3000/settings/ZQwjxYzBuSfodxHvF' },
I20150627-00:29:36.545(2)? { name: 'Twitter',
I20150627-00:29:36.546(2)? link: 'http://localhost:3000/settings/ZQwjxYzBuSfodxHvF' },
I20150627-00:29:36.546(2)? { name: 'LinkedIn',
I20150627-00:29:36.546(2)? link: 'http://localhost:3000/settings/ZQwjxYzBuSfodxHvF' } ],
I20150627-00:29:36.546(2)? user_id: 'ZQwjxYzBuSfodxHvF' }
After insert:
I20150627-00:31:23.185(2)? { settings_firm_name: 'Test',
I20150627-00:31:23.185(2)? settings_firm_primary_branch: 'test',
I20150627-00:31:23.185(2)? settings_firm_employees_num: 200,
I20150627-00:31:23.185(2)? settings_firm_address: 'Test',
I20150627-00:31:23.185(2)? settings_firm_contact_phone: '12345',
I20150627-00:31:23.186(2)? settings_firm_fax: '123445',
I20150627-00:31:23.186(2)? settings_firm_web_page: 'http://localhost:3000/settings/ZQwjxYzBuSfodxHvF',
I20150627-00:31:23.187(2)? settings_firm_email: 'test#hotmail.com',
I20150627-00:31:23.187(2)? settings_firm_social: [ {}, {}, {} ],
I20150627-00:31:23.187(2)? user_id: 'ZQwjxYzBuSfodxHvF' }

You can add a new schema object to validate settings_firm_social.
Schema.settings = new SimpleSchema({
settings_firm_social: {
type: [settingsFirmSocialSchema]
}
});
And then:
var settingsFirmSocialSchema = new SimpleSchema({
name: {
type: String
},
link: {
type: String
}
});

Related

How to use mongoose transactions with updateMany?

I am using the mongoose updateMany() method and I also want to keep it a part of transaction. The documentation shows the example of save() where I can do something like Model.save({session: mySession}) but don't really know how to use it with for example Model.updateMany()
UPDATE:
For example I have two models called SubDomain and Service and they look like this respectively:
SUB-DOMAIN
{
name: {
type: String,
required: true,
},
url: {
type: String,
required: true,
unique: true,
},
services: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Service",
},
],
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
}
SERVICE:
{
name: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
price: { type: Number },
tags: { type: Array },
packages: [
{
name: { type: String, required: true },
description: { type: String, required: true },
price: { type: Number, required: true },
},
],
map: { type: String },
isHidden: {
type: Boolean,
required: true,
default: false,
},
sortingOrder: { type: Number },
isForDomain: { type: Boolean, required: false, default: false },
isForSubDomain: { type: Boolean, required: false, default: false },
subDomains: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "SubDomain",
},
],
}
Now the main field here is the services field in SubDomain and subDomains field in Service.
The complicated part😅:
Whenever the user wants to create new service, I want to $push that service's _id into the array of services of all the subDomains inside that new service
And for that, I am using the updateMany() like this:
const sess = await mongoose.startSession();
sess.startTransaction();
const newService = new Service({
_id: mongoose.Types.ObjectId(),
subDomains: req.body.subDomains
...foo
})
await SubDomain.updateMany(
{ _id: { $in: req.body.subDomains } },
{ $push: { services: newService._id } }
);
The problem starts here, of course I can do:
newService.save({session: sess})
but how do I keep my SubDomain's updateMany in the same transaction (i.e sess)
I know my example is difficult to wrap your head around but I have tried to pick a simplest example rather than copying the exact same code which would have been a lot more difficult

Issue when login and register with Facebook in Meteor

I'm trying to use Facebook to connect and register into my Meteor.js application. In my login template I put a button to do this. I call the function Meteor.loginWithFacebook() but it doesn't work... I'm guessing that Meteor try to create a new user and that it doesn't find the username information but I don't know how to manage that.
My handler to call the login :
'click #facebook-login': function(event) {
Meteor.loginWithFacebook({}, function(err){
if (err) {
throw new Meteor.Error("Facebook login failed");
Materialize.toast('Echec de connexion!', 4000);
}
else {
Router.go(Utils.pathFor('home'));
Materialize.toast('Bon retour parmis nous ' + Meteor.user().username + ' !', 5000);
}
});
}
The error I have :
I20160428-12:44:56.099(2)? Exception while invoking method 'login' Error: Nom d'utilisateur is required
I20160428-12:44:56.100(2)? at getErrorObject (packages/aldeed_collection2-core/lib/collection2.js:437:1)
I20160428-12:44:56.101(2)? at [object Object].doValidate (packages/aldeed_collection2-core/lib/collection2.js:420:1)
I20160428-12:44:56.101(2)? at [object Object].Mongo.Collection. (anonymous function) [as insert] (packages/aldeed_collection2-core/lib/collection2.js:173:1)
I20160428-12:44:56.101(2)? at AccountsServer.Ap.insertUserDoc (packages/accounts-base/accounts_server.js:1250:25)
I20160428-12:44:56.101(2)? at AccountsServer.Ap.updateOrCreateUserFromExternalService (packages/accounts-base/accounts_server.js:1386:20)
I20160428-12:44:56.102(2)? at [object Object].Package (packages/accounts-oauth/oauth_server.js:55:1)
I20160428-12:44:56.103(2)? at packages/accounts-base/accounts_server.js:464:32
I20160428-12:44:56.103(2)? at tryLoginMethod (packages/accounts-base/accounts_server.js:241:14)
I20160428-12:44:56.103(2)? at AccountsServer.Ap._runLoginHandlers (packages/accounts-base/accounts_server.js:461:18)
I20160428-12:44:56.103(2)? at [object Object].methods.login (packages/accounts-base/accounts_server.js:524:27)
I20160428-12:44:56.129(2)? Sanitized and reported to the client as: Nom d'utilisateur is required [400]
User schema :
Globals.schemas.UserProfile = new SimpleSchema({
firstName: {
type: String,
regEx: /^[a-zA-Z-]{2,25}/,
optional: true,
label: "Prénom"
},
lastName: {
type: String,
regEx: /^[a-zA-Z-]{2,25}/,
optional: true,
label: "Nom"
},
birthDay: {
type: Date,
optional: true,
label: "Date de naissance",
min: new Date("1900-01-01T00:00:00.000Z"),
autoform: {
value: new Date("1900-10-18T00:00:00.000Z")
}
},
gender: {
type: String,
allowedValues: ['M', 'F'],
optional: true,
label: "Genre",
autoform: {
options: [
{
label: "Homme",
value: "M"
},
{
label: "Femme",
value: "F"
}
],
firstOption: "(Veuillez sélectionner une réponse)"
}
},
level: {
type: Number,
autoValue: function () {
if (this.isInsert) {
return 1;
}
},
autoform: {
omit: true
},
min: 0,
max: 1000,
label: "Niveau"
},
picture: {
type: String,
optional: true,
autoform: {
omit: true
},
label: "Photo"
}
});
// Schéma principal
Globals.schemas.User = new SimpleSchema({
username: {
type: String,
regEx: /^[a-z0-9A-Z_]{3,30}$/,
label: "Nom d'utilisateur"
},
password: {
type: String,
label: "Mot de passe",
optional: true,
autoform: {
afFieldInput: {
type: "password"
}
}
},
confirmation: {
type: String,
label: "Confirmation",
optional: true,
custom: function(){
if(this.value !== this.field('password').value){
return "passwordMissmatch";
}
},
autoform: {
afFieldInput: {
type: "password"
}
}
},
emails: {
type: [Object],
optional: false,
label: "Adresses Email"
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email,
label: "Adresses Email"
},
"emails.$.verified": {
type: Boolean,
optional: true,
autoform: {
omit: true
}
},
createdAt: {
type: Date,
autoValue: function () {
if (this.isInsert) {
return new Date;
} else {
this.unset();
}
},
autoform: {
omit: true
}
},
profile: {
type: Globals.schemas.UserProfile,
optional: true
},
services: {
type: Object,
optional: true,
blackbox: true,
autoform:{
omit: true
}
},
roles: {
type: Object,
optional: true,
blackbox: true,
autoform: {
omit: true
}
}
});
Thank's for any help !
The problem is that your schema requires Meteor.users to have a username field, which they don't contain by default. You can, however, generate this field by taking their name name from the Facebook profile.
Accounts.onCreateUser(function(options, user) {
user.username = user.services.facebook.name;
return user;
});
http://docs.meteor.com/#/full/accounts_oncreateuser

meteor: add some value to nested documents

I'm trying to add a value to a nested schema:
groups = new SimpleSchema({
title: { type: String, optional: true },
element: { type: [elements], optional: true }
});
elements = new SimpleSchema({
description:{ type: String, optional: true },
anything: { type: String, optional: true }
});
MongoDB.attachSchema(new SimpleSchema({
title: { type: String },
slug: { type: String, unique: true },
language: { type: String, defaultValue: "en" },
group: { type: [groups], optional: true },
}));
Now I want to add just a new element-description to an existing entry in the DB. I tried this, but it doesn't work.
Uncaught Error: When the modifier option is true, validation object must have at least one operator
var newElement = {
description: 'insert this as a new element description'
};
MongoDB.update({ _id: Id }, { $push: { 'group.element': newElement }}, function(error) { if(error) console.warn(error); });
Is it correct to use 'group.element' as a $push-parameter?
Update
I forgot the index of group: $push: { 'group.0.element': newElement }
Also I have to define elements before groups in the schema.

Meteor Simple Schema - When the modifier option is true, validation object must have at least one operator

I keep getting the error: Exception while invoking method 'createUser' Error: When the modifier option is true, validation object must have at least one operator when I try to create a user. I am using meteor-simple-schema, but none of the fixes with this error have worked for me. I have tried using blackbox and optional to see where the issue is but I keep getting the same error.
var Schemas = {};
Schemas.UserGamesPart = {
public: {
type: [String],
defaultValue: []
},
private: {
type: [String],
defaultValue: []
}
};
Schemas.UserGames = {
game1: {
type: Schemas.UserGamesPart
}
};
Schemas.UserProfile = new SimpleSchema({
games: {
type: Schemas.UserGames
}
});
Schemas.UpgradeDetails = new SimpleSchema({
subscribed_on: {
type: Date,
optional: true
},
stripe_charge_id: {
type: String,
optional: true
},
school_license: {
type: Boolean,
defaultValue: false,
optional: true
}
});
Schemas.UserProperties = new SimpleSchema({
paid: {
type: Boolean,
defaultValue: false
},
upgrade_details: {
type: Schemas.UpgradeDetails,
optional: true
}
});
Schemas.User = new SimpleSchema({
_id: {
type: String
},
username: {
type: String,
optional: true
},
emails: {
type: [Object]
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email,
optional: true
},
"emails.$.verified": {
type: Boolean,
optional: true
},
createdAt: {
type: Date
},
profile: {
type: Schemas.UserProfile,
blackbox: true,
optional: true
},
properties: {
type: Schemas.UserProperties,
blackbox: true,
optional: true
}
});
Meteor.users.attachSchema(Schemas.User);
My accounts.creaate user is as follows:
Accounts.createUser({
email: $('#email').val(),
password: $('#password').val(),
profile: {
games: {
game1: {
public: [],
private: []
}
}
}
});
Any ideas on how I can get this to work?
You forgot to add new SimpleSchema there in the beginning:
Schemas.UserGamesPart = new SimpleSchema({
public: {
type: [String],
defaultValue: []
},
private: {
type: [String],
defaultValue: []
}
});
Schemas.UserGames = new SimpleSchema({
game1: {
type: Schemas.UserGamesPart
}
});
Also I think your usage of the nested schemas is a little off. Only nest schemas when you need to reuse one. Creating a separate schema for UserGamesPart looks horrible. Try this instead:
Schemas.UserGames = new SimpleSchema({
game1: {
type: Object
}
'game1.public': {
type: [String],
defaultValue: []
},
'game1.private': {
type: [String],
defaultValue: []
}
});
This is shorter and easier to read.

Uncaught Error: When the modifier option is true, validation object must have at least one operator

trying to read between StackOverflow and the documentation of meteor-simple-schema but can't find a solution. I'trying to insert data in the Meteor.users collection through a form. But keep getting an error:
Uncaught Error: When the modifier option is true, validation object must have at least one operator
checkModifier
# simple-schema-validation.js:271doValidation1 # simple-schema-validation.js:321doValidation # simple-schema-context.js:9simpleSchemaValidationContextValidate # simple-schema-context.js:44doValidate # collection2.js:317_.each.Mongo.Collection.(anonymous function) # collection2.js:154(anonymous function) # VM47084:2InjectedScript._evaluateOn # VM47083:883InjectedScript._evaluateAndWrap # VM47083:816InjectedScript.evaluate # VM47083:682
Any clue?
if (Meteor.isClient) {
Template.artistform.events({
'submit': function (event) {
event.preventDefault(); //prevent page refresh
var currentUserId = this.userId;
form={firstName:firstname.value, lastName:lastname.value};
Meteor.users.update({_id:currentUserId}, {$set:form});
}
});
}
And the Schema
Schema = {};
Schema.UserCountry = new SimpleSchema({
name: {
type: String,
optional: true
},
code: {
type: String,
regEx: /^[A-Z]{2}$/,
optional:true
}
});
Schema.UserProfile = new SimpleSchema({
firstName: {
type: String,
regEx: /^[a-zA-Z-]{2,25}$/,
optional: true
},
lastName: {
type: String,
regEx: /^[a-zA-Z]{2,25}$/,
optional: true
},
birthday: {
type: Date,
optional: true
},
category : {
type: String,
allowedValues: ['Painting', 'Music','Other'],
optional: true
},
website: {
type: String,
regEx: SimpleSchema.RegEx.Url,
optional: true
},
bio: {
type: String,
optional: true
},
country: {
type: Schema.UserCountry,
optional: true
}
});
Schema.User = new SimpleSchema({
email: {
type: String,
optional: true
},
"email.verified": {
type: Boolean,
optional: true
},
profile: {
type: Schema.UserProfile,
optional: true
},
createdAt: {
type: Date,
autoValue: function() {
if (this.isInsert) {
return new Date();
} else if (this.isUpsert) {
return {$setOnInsert: new Date()};
} else {
this.unset();
}
}
}
});
Meteor.users.attachSchema(Schema.User);
Many thanks.
Try this schema
Schema.User = new SimpleSchema({
email: {
type: Object
},
'email.address': {
type: String,
optional: true
},
"email.verified": {
type: Boolean,
optional: true
},
profile: {
type: Schema.UserProfile,
optional: true
},
createdAt: {
type: Date,
autoValue: function() {
if (this.isInsert) {
return new Date();
} else if (this.isUpsert) {
return {$setOnInsert: new Date()};
} else {
this.unset();
}
}
}
});
Btw if you are using account-password then this schema won't work as that package expect emails to be stored in a certain way.

Categories