How to make strict associations in Sails.js - javascript

Here are my two models that were generated using sails generate api model_name
Guitar.js
module.exports = {
schema: true,
attributes: {
brand:{
type: 'string',
required: true
},
messages:{
collection: 'message',
via: 'guitar'
}
}
};
Message.js
module.exports = {
schema: true,
attributes: {
text:{
type: 'string',
required: true
},
author:{
type: 'string',
defaultsTo: 'Anonymous author'
},
guitar:{
model: 'guitar',
required: true
}
}
};
Basically, a guitar can have many messages.
The problem comes when I insert new messages into the DB:
POST http://localhost:1337/message/
With JSON content:
{
"text": 4,
"author": "33434",
"guitar": null,
"extra": "This attribute will be removed because schema: true"
}
If I send this, the server will throw an error because the message must have a guitar.
However, if I instead write "guitar": 34, and 34 is a guitar ID that doesn't exist, the message will be added, and guitar will be changed to null. Weird.
This seems to be a bug, or maybe it's the intended behaviour but with a NoSQL database in mind.
I need to make strict associations so that all data makes sense. I hope I don't have to create my own controller manually that handles this logic the way I want.
Basically what I want is that Sails throws an error when the ID of the association doesn't exist.
By the time I write this, I came up with a solution: Just configure this on the DB server (MySQL, etc) so that the foreign key must exist and then handle the error in Sails. But I'm not very happy with it since it depends on the DB server. I'd like this to work even with localDiskDb.
My other solution would be to actually write manually a controller and see what happens by using something like Guitar.find(id).add(new_message) (maybe it's wrong, I haven't tested this)

I am not sure about this but have you tried like this :
http://localhost:1337/message/create?text=4&author=3343&guitar=somerandomString

Related

mongodb not detecting unique value in my node js project

I'm working on mongodb with node js and I realized that even though I used the unique true property on unique fields in my project, I realized that it doesn't work, what is the reason?
my code is like this
const CourseSchema = new Schema({
name: {
type: String,
required : true,
unique:true
},
description: {
type: String,
required: true,
trim: true,
},
createdAt: {
type: Date,
default: Date.now,
},
});
i want to prevent this code from saving duplicate usernames.
Such a check if not directly possible with the mongoDB library. However it is supported out of the box if you use mongoosejs
It may be possible that you already have duplicate values in your document before defining this property Delete the messed data from the MongoDB collections,
or make sure that mongodb auto indexing is true
mongoose.connect('url', {
useNewUrlParser: true,
useCreateIndex: true,
autoIndex: true,
})
I tried many ways, but I realized that this problem is version-related.
I found the solution by updating the version, thank you for your solution support.

Duplicate key error while using _id from another collection

I have 2 collections so far.
The first is a 'Users' collection (That works well), and the other is a 'Rooms' collection (both created for a chat application).
I want every room to have a "users" array that will contain the user._id of every user that is in that room,
meaning I should be able to put the same user._id (from the user collection) in every one of the rooms right?
After creating a room successfully with 2 user._ids in the "users" array,
I tried making another one using one of the user._ids I used in the first room.
Then I got this error:
MongoError: E11000 duplicate key error collection: ratchat.rooms index: users_1 dup key:
{ users: "5fe08d452f34530e641d8f8c" }
After checking with a debugger I've found that the error occurs only when I use a user._id that is already used in another room's "users" array.
The only thing I could think of that could cause this problem is the Room schema,
maybe there's something I missed while reading the docs...
At first my Room schema looked like this:
const roomSchema = new mongoose.Schema({
users: [String],
hasLeft: [String],
isGroup: { type: Boolean, default: false },
},
});
const Room = mongoose.model("Room", roomSchema);
Then I thought maybe mongoDB needs to know that the ObjectIds that are in the users array are just references to another collection:
const roomSchema = new mongoose.Schema({
users: [{ type: mongoose.Schema.Types.ObjectId, ref: "User" }],
hasLeft: [String],
isGroup: { type: Boolean, default: false },
},
});
const Room = mongoose.model("Room", roomSchema);
No luck so far...
{autoIndex: false}
After research, I have found the reason for this error:
mongoose automatically creates indexes,
this is not only a duplicate error issue, but can cause a significant performance impact later in production.
According to mongoose docs, you can easily disable this behavior by setting the autoIndex option of your schema to false, or globally on the connection by setting the option autoIndex to false.
mongoose.connect('mongodb://user:pass#localhost:port/database', { autoIndex: false });
// or
mongoose.createConnection('mongodb://user:pass#localhost:port/database', { autoIndex: false });
// or
animalSchema.set('autoIndex', false);
// or
new Schema({..}, { autoIndex: false });
Don't forget to drop the entire collection before trying again
Because the collection is already indexed, emptying it completely won't work.
You have to drop the entire collection.

Sequelize: Change "validate" meta data of column

Is it possible to change the "validate" meta data of a column using a migration file? I tried the queryInterface.changeColumn method and it seems like it can only change the three meta data mentioned in the docs (defaultValue, allowNull, and type).
I've tried doing something like this inside the 'up' object of the migration file:
queryInterface.changeColumn(
'tableName',
'columnName',
{
validate: {
is: /new_regex_validation/
}
}
)
However, the above attempt did not work for me when I ran "sequelize db:migrate"
For simplicity's sake, I'll use a table definition to elaborate on my question:
I'm trying to change an already existing table like this:
var tableName = sequelize.define('tableName', {
columnName: {
type: DataTypes.STRING,
unique: true,
allowNull: false,
validate: {
is: /some_regex_validation/
}
}
})
into this using sequelize migration:
var tableName = sequelize.define('tableName', {
columnName: {
type: DataTypes.STRING,
unique: true,
allowNull: false,
validate: {
is: /a_new-or-different_regex_validation/
}
}
})
or simply remove the validate meta data while using sequelize migration:
var tableName = sequelize.define('tableName', {
columnName: {
type: DataTypes.STRING,
unique: true,
allowNull: false
}
})
Any ideas?
Validation happens on the client, not on the database. You don't need a migration for it.
I came across this question a few times trying to understand the difference between building my model with validations and using migrations.
I found this link very helpful. Hopefully someone else does in the future.
Difference between Validations and Constraints
Validations are checks performed in the Sequelize level, in pure
JavaScript. They can be arbitrarily complex if you provide a custom
validator function, or can be one of the built-in validators offered
by Sequelize. If a validation fails, no SQL query will be sent to the
database at all.
On the other hand, constraints are rules defined at SQL level. The
most basic example of constraint is an Unique Constraint. If a
constraint check fails, an error will be thrown by the database and
Sequelize will forward this error to JavaScript (in this example,
throwing a SequelizeUniqueConstraintError). Note that in this case,
the SQL query was performed, unlike the case for validations.
https://sequelize.org/master/manual/validations-and-constraints.html

Create multiple user contracts in Meteor

I want to create a system where multiple contracts can be created belonging to different users.
In Django, Ruby, etc., I would create a model Contract with field user = models.ForeignKey(settings.AUTH_USER_MODEL) but I don't know how to do this in Meteor.
Is it better to make a schema with
Schema.User = new SimpleSchema({
contracts: {
type: [Object],
},
"contracts.$.start_date": {
type: Date,
},
"contracts.$.end_date": {
type: Date,
},
"contracts.$.salary": {
type: Number,
}
});
or something like that? And then use meteor-autoform to create these? It seems very difficult to make objects relational in Meteor.
MongoDB isn't a relational database and so you'll need to manually handle relationships yourself (using multiple queries). Traditionally a Mongo document would use embedding whenever possible and use separate collections when necessary. See here for more information:
MongoDB relationships: embed or reference?
However, Meteor throws a spanner in the works since the publish model can only publish top-level documents, and there's little support for document hierarchies when writing templates etc.
Therefore the normal approach under Meteor is to create table for each collection and to have a records refer to other records using an ID:
Schema.User = new SimpleSchema({
contracts: {
type: [String],
},
...
});
Schema.Contract = new SimpleSchema({
user: {
type: String,
index: true
},
...
});
Although this will result in you having to do multiple queries, the structure will work very will with Meteor's design philosophies.

JayData provider failing to load for sqLite and indexedDb

I'm trying to use JayData using the sqLite provider via
myDB = new MyDatabase({ provider: 'sqLite' , databaseName: 'MyDB', version: 1 });
But when It runs this line it echos to console the following message twice
"Provider fallback failed!"
I have tried manually loading the sqLite provider and not loading it but it did not fix the issue.
If I swap the provider setting to 'indexedDb' the JayData js is automatically trying to load the IndexedDbProvider.js class from the wrong directory
GET http://192.168.2.49/Test/jaydataproviders/IndexedDbProvider.js
when it should be
GET http://192.168.2.49/Test/js/Jaydata/jaydataproviders/IndexedDbProvider.js
Does anyone know either why I am getting the error using sqLite or how to get the provider to auto load from the correct directory? I have also tried loading the indexedDB provider manually but it does not fix the issue and it still tries to load the provider incorrectly
I have copied the latest JayData code straight into the SiteRoot/js folder under Jaydata it should be self consistent within that folder I haven’t changed or moved any files
My database schema is large but essentially similar to the following entity and database definition
$data.Entity.extend("Image", {
id: { type: "int", key: true, computed: true },
location: { type: String, required: true, maxLength: 500 },
classification: { type: "int", required: true },
name: { type: String, maxLength: 500 }
});
$data.Entity.extend("Inventory", {
id: { type: "int", key: true, computed: true },
name: { type: String, required: true, maxLength: 200 },
description: { type: String, required: true, maxLength: 1000 },
imageId: { type: "int", required: true}
});
$data.EntityContext.extend("MyDatabase", {
Images: { type: $data.EntitySet, elementType: Image } ,
Inventories: {type: $data.EntitySet, elementType: Inventory }
});
I have some js code from here that specifically loads the correct js files in sequence using getScript and debugging in firefox confirms the files are loading in order
I am loading the files in the following sequence
Jquery 2.1.3
/js/Jaydata/jaydata.js (The default Jaydata.js file unmodified)
/js/DB/DBSchema.js (My schema defining the database objects)
/js/DB/DBUtilities.js (Some functions to help working with the database)
/js/main.js
Step 5 on page ready $(function() assigns the database variable and onReady checks if the database is initialized
myDB = new MyDatabase({ provider: 'indexedDb' , databaseName:'MyDB', version: 1 });
myDB.onReady(function() {
logThis('Connected to DB');
checkIfInitilizeIsNeeded();
});
This is where the provider fails to load
Thanks for any help
According to this page JayData doesnt support firefox using webSql or sqLite though it should have worked with indexeddb
I've tested it using chrome and it seems to be happy so yea little dodgy 2nd most popular browser on the planet but nm

Categories