I'm trying to add an object to an object array that is a key in a collection entry with the following code, but I'm getting a weird response "insert failed: Error: Title is required". I'm using simple schema/autoform on meteor.
Has anyone encountered this before (and have a solution)?
Template.dashboard.events({
'click .requestinvite'(e,t) {
Posts.insert({ _id : $(e.currentTarget).attr('_id')},
{$push: { invitesRequested : {username : Meteor.userId()} }}
);
}
});
Here is the relevant Simple Schema in coffeescript
Schemas.Posts = new SimpleSchema
title:
type:String
max: 60
optional: true
content:
type: String
optional: false
autoform:
rows: 5
createdAt:
type: Date
autoValue: ->
if this.isInsert
new Date()
updatedAt:
type:Date
optional:true
autoValue: ->
if this.isUpdate
new Date()
invitesRequested:
type: [Object]
optional: true
defaultValue: []
owner:
type: String
regEx: SimpleSchema.RegEx.Id
autoValue: ->
if this.isInsert
Meteor.userId()
autoform:
options: ->
_.map Meteor.users.find().fetch(), (user)->
label: user.emails[0].address
value: user._id
First of all as per proper javascript assignment standards, you are doing blunder in your code.
What if your code is hacked and the click event is called without any id assigned?
Your code must be as follows.
Template.dashboard.events({
'click .requestinvite'(e,t) {
var id = $(e.currentTarget).attr('_id');
if(id){
Posts.insert(
{
_id : id
},
{
$push: {
invitesRequested : {username : Meteor.userId()}
}
}
);
} else {
//do something here when you don't have id here, or the `click` event is hacked on UI to work without id'
}
}
});
Since your SimpleSchema is giving error regarding title field, if it is not mandatory, then kindly use optional : true at the point of defining title field.
e.g.
title: {
type: String,
label: "Title",
optional: true //<---- do this
}
NOTE: By default, all keys are required. Set optional: true to change that.
The answer was using Posts.update instead. But Ankur Soni's post lead me in the right direction to troubleshoot this down.
Related
I have a Dynamoose (DynamoDB) model called PromoCode with a schema that looks like this:
{
promoCode: {
hashKey: true,
type: String,
},
previouslyUsed: {
type: Boolean,
default: false,
index: {
global: true,
name: 'previouslyUsedIndex',
},
},
promoGroup: {
type: String,
index: {
global: true,
name: 'promoGroupIndex',
},
},
}
Essentially, I have a table full of promo codes and I want to get a single promo code that hasn't been used and is part of a particular "group" of promo codes.
So, I want to query on both previouslyUsed and promoGroup fields and limit the results to a single results. This is what I came up with:
PromoCode.query('previouslyUsed').eq(false)
.and()
.filter('promoGroup').eq('friend').limit(1)
This returns no results, even though I know that the query should match a result. If I increase the limit to 10, then I get back four results. This makes me think that the limit is happenning before the and() thus the preceding filter() is only filtering on the 10 returned results where previouslyUsed=false.
How do I take a single result where the conditions previouslyUsed=false and promoGroup=friend are valid?
So, here's what I figured out (to answer my own question). Firstly, using filter will only filter the results that are pulled from the database. So, I wasn't experiencing some weird bug.
Secondly, what I really wanted was a range key setup. This will give me the following schema:
{
promoCode: {
hashKey: true,
type: String,
},
previouslyUsed: {
type: Boolean,
default: false,
index: {
global: true,
name: 'previouslyUsedIndex',
rangeKey: 'promoGroup',
},
},
promoGroup: {
type: String,
rangeKey: true,
index: true,
},
}
Note the use of both instances of rangeKey above. Evidently both are necessary to do the following query:
PromoCode.query('previouslyUsed').eq(false)
.where('promoGroup').eq('friend')
It's actually as "simple" as that. This let's me filter on two different fields.
I'd like use this schema as user and login or extend form users.I read documentation and I don't understand how extends from users. how I can make it?
Dipendenti = new Mongo.Collection('dipendenti');
DipendentiSchema = new SimpleSchema({
nome: {
type: String
},
cognome:{
type: String
},
codiceFiscale:{
type: String
},
telefono:{
type: String
},
indirizzo:{
type: String
}
});
I believe you are trying to extend/merge the schema listed above to the users collection. If so, you just need to attach the schema to the collection.
Meteor.users.attachSchema(DipendentiSchema);
UPDATE:
To use this new merged schema, you should be able to do something like:
Accounts.createUser({
username: 'test',
email: 'test#example.com',
password: 'password',
nome: 'Richard',
cognome: 'Ortiz',
codiceFiscale: 'EUR',
telefono: '+39 06 49911',
indirizzo: 'Piazzale Aldo Moro, 5, 00185 Roma, Italy'
});
If you want to make email address optional in your schema, you can add the following to it.
emails: {
optional: true,
type: [Object]
},
"emails.$.address": {
optional: true,
type: String
},
"emails.$.verified": {
optional: true,
type: Boolean
}
UPDATE 2:
Ensure that you are defining and attaching the schema wherever you are trying to make changes to the users collection. It is generally considered a best practice to do your database changes only on the server for security. You could write a method on the server using Meteor.methods({}); and then call it on the client with Meteor.call({}); and pass it your user data. You can read more about this approach the Meteor documentation.
I'm fairly new to MongoDb / Mongoose, more used to SQL Server or Oracle.
I have a fairly simple Schema for an event.
EventSchema.add({
pkey: { type: String, unique: true },
device: { type: String, required: true },
name: { type: String, required: true },
owner: { type: String, required: true },
description: { type: String, required: true },
});
I was looking at Mongoose Indexes which shows two ways of doing it, I used the field definition.
I also have a very simple API that accepts a POST and calls create on this collection to insert the record.
I wrote a test that checks that the insert of a record with the same pkey should not happen and that the unique:true is functioning. I already have a set of events that I read into an array so I just POST the first of these events again and see what happens, I expected that mongo DB would throw the E11000 duplicate key error, but this did not happen.
var url = 'api/events';
var evt = JSON.parse(JSON.stringify(events[0]));
// POST'ed new record won't have an _id yet
delete evt._id;
api.post(url)
.send(evt)
.end(err, res) {
err.should.exist;
err.code.should.equal(11000);
});
The test fails, there is no error and a duplicate record is inserted.
When I take a look at the collection I can see two records, both with the same pkey (the original record and the copy that I posted for the test). I do notice that the second record has the same creation date as the first but a later modified date.
(does mongo expect me to use the latest modified version record???, the URL is different and so is the ID)
[ { _id: 2,
pkey: '6fea271282eb01467020ce70b5775319',
name: 'Event name 01',
owner: 'Test Owner',
device: 'Device X',
description: 'I have no idea what\'s happening',
__v: 0,
url: '/api/events/2',
modified: '2016-03-23T07:31:18.529Z',
created: '2016-03-23T07:31:18.470Z' },
{ _id: 1,
pkey: '6fea271282eb01467020ce70b5775319',
name: 'Event name 01',
owner: 'Test Owner',
device: 'Device X',
description: 'I have no idea what\'s happening',
__v: 0,
url: '/api/events/1',
modified: '2016-03-23T07:31:18.470Z',
created: '2016-03-23T07:31:18.470Z' }
]
I had assumed that unique: true on the field definition told mongo db that this what you wanted and mongo enforced that for you at save, or maybe I just misunderstood something...
In SQL terms you create a key that can be used in URL lookup but you can build a unique compound index, to prevent duplicate inserts. I need to be able to define what fields in an event make the record unique because on a form data POST the submitter of a form does not have the next available _id value, but use the _id (done by "mongoose-auto-increment") so that the URL's use from other parts of the app are clean, like
/events/1
and not a complete mess of compound values, like
/events/Event%20name%2001%5fDevice%20X%5fTest%20Owner
I'm just about to start coding up the so for now I just wrote a simple test against this single string, but the real schema has a few more fields and will use a combination of them for uniqueness, I really want to get the initial test working before I start adding more tests, more fields and more code.
Is there something that I should be doing to ensure that the second record does not actually get inserted ?
It seems that you have done unique indexing(at schema level) after inserting some records in db.
please follow below steps to avoiding duplicates -
1) drop your db:
$ mongo
> use <db-name>;
> db.dropDatabase();
2) Now do indexing at schema level or db level
var EventSchema = new mongoose.Schema({
pkey: { type: String, unique: true },
device: { type: String, required: true },
name: { type: String, required: true },
owner: { type: String, required: true },
description: { type: String, required: true },
});
It will avoid duplicate record insertion with same pKey value.
and for ensuring the index, use command db.db_name.getIndexes().
I hope it helps.
thank you
OK it looks like it has something to do with the index not having time to update before the second insert is posted (as there is only 9ms between them in my test suite).
need to do something about inserts waiting for "index"
needs to be API side as not all users of the API are web applications
I also found some other SO articles about constraints:
mongoose unique: true not work
Unique index not working with Mongoose / MongoDB
MongoDB/Mongoose unique constraint on Date field
on mongoose.connect add {useCreateIndex: true}
It should look like this
mongoose.connect(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true
})
add:
EventSchema.index({ pkey: 1 }, { unique: true });
// Rebuild all indexes
await User.syncIndexes();
worked for me.
from https://masteringjs.io/tutorials/mongoose/unique
I'm a meteor and coding newbie. I've spent all day trying to use aldeed:autoform and aldeed:collection2 to add profile information to Meteor.users. My success varied, and I almost got what I wanted (posted to mongo, but created new id instead of attaching to current) but lost where I was somehow. Now, I keep getting
SimpleSchema invalid keys ... 0: Object
name: "emails"
type: "expectedArray"
And nothing I 'submit' gets posted to Mongo at all.
Here are all the things I think I need:
collections/simpleSchema.js
Meteor.users.allow({
update: function (userId, doc){
return !!userId;
}
});
Schema.UserProfile = new SimpleSchema({
firstName: {
type: String,
optional: true
},
lastName: {
type: String,
optional: true
},
birthday: {
type: Date,
optional: true
},
grade: {
type: String,
allowedValues: ['5', '6', '7', '8'],
optional: true
}
});
Schema.User = new SimpleSchema({
username: {
type: String,
// For accounts-password, either emails or username is required, but not both. It is OK to make this
// optional here because the accounts-password package does its own validation.
// Third-party login packages may not require either. Adjust this schema as necessary for your usage.
optional: true,
autoform: {
type: "hidden"
}
},
emails: {
type: Array,
// For accounts-password, either emails or username is required, but not both. It is OK to make this
// optional here because the accounts-password package does its own validation.
// Third-party login packages may not require either. Adjust this schema as necessary for your usage.
optional: true,
autoform: {
type: "hidden"
}
},
"emails.$": {
type: Object,
autoform: {
type: "hidden"
}
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email,
autoform: {
type: "hidden"
}
},
// "emails.$.verified": {
// type: Boolean
// },
createdAt: {
type: Date,
optional: true,
autoValue: function(){
return new Date();
},
autoform: {
type: "hidden"
}
},
profile: {
type: Schema.UserProfile,
optional: true
},
// Make sure this services field is in your schema if you're using any of the accounts packages
services: {
type: Object,
optional: true,
blackbox: true,
autoform: {
type: "hidden"
}
}
// Add `roles` to your schema if you use the meteor-roles package.
// Option 1: Object type
// If you specify that type as Object, you must also specify the
// `Roles.GLOBAL_GROUP` group whenever you add a user to a role.
// Example:
// Roles.addUsersToRoles(userId, ["admin"], Roles.GLOBAL_GROUP);
// You can't mix and match adding with and without a group since
// you will fail validation in some cases.
//roles: {
// type: Object,
// optional: true,
// blackbox: true
//}
// Option 2: [String] type
// If you are sure you will never need to use role groups, then
// you can specify [String] as the type
// roles: {
// type: [String],
// optional: true
// }
});
Meteor.users.attachSchema(Schema.User);
client.js
SimpleSchema.debug = true
Template.NewUser.helpers({
updateUserForm: function(){
return Meteor.user;
}
});
server.js
Meteor.methods({
update: function(doc) {
// Important server-side check for security and data integrity
check(doc, Meteor.users);
Meteor.users.clean(doc);
}
});
Thank you for reading!
you didn't include your html in your content. However it appears like you are making use of a method update on your auto form. In order for this to work in your server you need to call the Meteor.user.update() operator.
updateProfile: function(doc, doc_id) {
var theUser = Meteor.users.findOne({
_id: doc_id
});
if (theUser._id !== Meteor.userId()) {
throw new Meteor.Error("Not Authorised");
} else {
Meteor.users.update({
_id: doc_id
}, doc);
}
},
I have
Schema.User = new SimpleSchema({
fullName: {
type: String,
},
contracts: {
type: [Object],
},
"contracts.$.start_date": {
type: Date,
},
"contracts.$.end_date": {
type: Date,
},
"contracts.$.salary": {
type: Number,
}
});
Meteor.users.attachSchema(Schema.User);
Not I want to display the form in my template, making it possible to update name and add/remove/update contracts.
I have tried
{{> quickForm collection="Meteor.users" id="updateUserContractsForm" type="update" doc=this fields="fullName,contracts"}}
but I can only update fullName. If I am trying to add new contracts, they wont get saved. I guess it's because I have type="update" instead of type="insert", so it wont allow me to insert edit the contracts since they don't exist yet.
Am I right? Can I do something to mix insert/update?