How to configure unique key with multiple field in SimpleSchema - meteor

I'm using SimpleSchema in meteor app. Now I need to define unique key with multiple field. In a Collection I have field like
servingDate, vanId, timeSlot
I need to make a unique with those three fields. Is there any possibilities to do in SimpleSchema ??

You cannot do that from with a simple schema configuration. Your only valid option is:
if (Meteor.isServer) {
MyCollection._ensureIndex(
{servingDate: 1, vanId: 1, timeSlot: 1},
{ unique: true }
);
}

Related

Getting the right permitted fields of conditions

Currently, I'm building an app with with following similar logic:
...
const user = {
isAdmin: true,
company: '5faa6a847b42bf47b8f785a1',
projects: ['5faa6a847b42bf47b8f785a2']
}
function defineAbilityForUser(user) {
return defineAbility((can) => {
if (user.isAdmin) {
can('create', 'ProjectTime', {
company: user.company,
}
);
}
can(
'create',
'ProjectTime',
["company", "project", "user", "start", "end"],
{
company: user.company,
project: {
$in: user.projects
}
}
);
});
}
const userAbility = defineAbilityForUser(user); //
console.log( permittedFieldsOf(userAbility, 'create', 'ProjectTime') );
// console output: ['company', 'project', 'user', 'start', 'end']
Basically an admin should be allowed to create a project time with no field restrictions.
And a none admin user should only be allowed to set the specified fields for projects to which he belongs.
The problem is that I would expect to get [] as output because an admin should be allowed to set all fields for a project time.
The only solution I found was to set all fields on the admin user condition. But this requires a lot of migration work later when new fields are added to the project time model. (also wrapping the second condition in an else-block is not possible in my case)
Is there any other better way to do this? Or maybe, would it be better if the permittedFieldsOf-function would prioritize the condition with no field restrictions?
There is actually no way for casl to know what means all fields in context of your models. It knows almost nothing about their shapes and relies on conditions you provide it to check that objects later. So, it does not have full information.
What you need to do is to pass the 4th argument to override fieldsFrom callback. Check the api docs and reference implementation in #casl/mongoose
In casl v5, that parameter is mandatory. So, this confusion will disappear very soon

Best way to exclude a Meteor value from the database?

What is the best way to exclude a field value from the data in Meteor when using Autoform, SimpleSchema, Collection2, etc? Say I have:
MySchema = new SimpleSchema({
password: {
type: String,
label: "Enter a password",
min: 8
},
confirmPassword: {
type: String,
label: "Enter the password again",
min: 8,
custom: function () {
if (this.value !== this.field('password').value) {
return "passwordMismatch";
}
}
}
});
... and I do not want to confirmPassword field persisted to the database, what is the best way to handle that? I assume using hooks, but if so where and how? Hopefully there is a way to just exclude one (or more) values without having to redefine the whole whole schema to say which to include and which to exclude. If I have 100 fields and want to exlcude 1, hopefullly the hook or whatever does not need the other 99 defiled too.
TIA
With autoform, you must use a method on the server side. Simply delete the field in the method code when you receive it at the server before inserting the document.

Objects with multiple key columns in realm.io

I am writing an app using the Realm.io database that will pull data from another, server database. The server database has some tables whose primary keys are composed of more than one field. Right now I can't find a way to specify a multiple column key in realm, since the primaryKey() function only returns a String optional.
This one works:
//index
override static func primaryKey() ->String?
{
return "login"
}
But what I would need looks like this:
//index
override static func primaryKey() ->[String]?
{
return ["key_column1","key_column2"]
}
I can't find anything on the docs on how to do this.
Supplying multiple properties as the primary key isn't possible in Realm. At the moment, you can only specify one.
Could you potentially use the information in those two columns to create a single unique value that you could use instead?
It's not natively supported but there is a decent workaround. You can add another property that holds the compound key and make that property the primary key.
Check out this conversation on github for more details https://github.com/realm/realm-cocoa/issues/1192
You can do this, conceptually, by using hash method drived from two or more fields.
Let's assume that these two fields 'name' and 'lastname' are used as multiple primary keys. Here is a sample pseudo code:
StudentSchema = {
name: 'student',
primaryKey: 'pk',
properties: {
pk: 'string',
name: 'string',
lastname: 'string',
schoolno: 'int'
}
};
...
...
// Create a hash string drived from related fields. Before creating hash combine the fields in order.
myname="Uranus";
mylastname="SUN";
myschoolno=345;
hash_pk = Hash( Concat(myname, mylastname ) ); /* Hash(myname + mylastname) */
// Create a student object
realm.create('student',{pk:hash_pk,name:myname,lastname:mylastname,schoolno: myschoolno});
If ObjectId is necessary then goto Convert string to ObjectID in MongoDB

Meteor update a Collection object

in Meteor, I'm having a collection with a Schema, and a number of items are added dynamically.
In this case, I'm dealing with milestones object, and once the user check one off I want to update complete in this Collections item to true (default is false)
Here is my schema
milestones: {
type: Array,
optional: true
},
'milestones.$': {
type: Object
},
'milestones.$.name': {
type: String
},
'milestones.$.hours': {
type: Number
},
'milestones.$.complete': {
type: Boolean
}
How do I write a $set statement for this?
You have an array of objects so, $elemMatch do the trick here.
Projects.update({_id:this._id},{milestones:{$elemMatch:{'milestones.$‌​.name':this.name}},{$set:{'milestone.$.complete':value}}})
So thanks to Aldeed I found a solution - which needs to be called on server side, otherwise it won't let the update happen. Do:
Projects.update({_id:currentPostId, 'milestones.name':name}, {$set:{'milestones.$.complete':true}});
The function is called on the client with Meteor.call with all needed params.
According to your schema you have an object containing an array of objects. So you should write you $set like this:
{$set: {'milestone.$.complete':value}}
This will update the first array element corresponding to the query.
You can find here the official documentation if you want to know more about arrays updates in Mongo.

Meteor Collection - How to mark a property as unique

How can I mark a property in a Meteor Collection as unique? I am trying to create a document collection with each document having a name that is unique, and I can't figure out how to make this unique.
You know that mongo assigns a unique, non-human based _id to every document, and that often the title a user decides to call something doesn't need to be unique. That being said,
http://docs.mongodb.org/manual/tutorial/create-a-unique-index/ tells you how to make an index that forces a field to be unique:
db.collection.ensureIndex( { a: 1 }, { unique: true } );
You can run that from the mongo shell. It can also be called from the server js only. If you've created a collection by
Diaries = new Meteor.collection();
then just after adding the collection, in server code, you could add
Diaries.ensureIndex({ title: 1},{ unique: true });

Resources