Sails.js composite unique field - sails.js

This model gives me the effect I want at the expense of duplicated data and general uglyness:
//Example
var Example = {
attributes: {
foo: {
type: 'string',
required: true
},
bar: {
type: 'string',
required: true,
},
baz: {
type: 'integer',
required: true,
min: 1
},
foobar: {
type: 'string',
unique: true
}
},
beforeValidation : function(values,cb) {
values.foobar = values.foo+values.bar;
cb();
}
};
module.exports = Example;
Is there a better strategy for creating a composite unique key?

There's no way to do this directly in sails see https://github.com/balderdashy/waterline/issues/221. The best solution is to do this directly in the db you plan to use.

Related

How to develop nested condition query in mongoDB

I am pretty new to mongoDb and want to apply nested query.
I have a business schema like this:
const businessSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
},
businessType: {
type: Schema.Types.ObjectId,
ref: "businessCategory",
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
select: false,
},
review: {
type: [reviewSchema],
},
isDeleted: {
type: Boolean,
default: false,
},
},
{ timestamps: true }
);
Business has a review where user can do the review and reviewSchema is
const reviewSchema = new mongoose.Schema(
{
user: {
type: Schema.Types.ObjectId,
ref: "users",
required: true,
},
rating: {
type: Number,
enum: [1, 2, 3, 4, 5],
},
reviewArray: {
type: [singleReviewSchema],
},
},
{ timestamps: true }
);
One user can do many reviews, and it has reviewArray.
ReviewArray schema is
const singleReviewSchema = new mongoose.Schema(
{
title: {
type: String,
},
description: {
type: String,
},
isDeleted: {
type: Boolean,
default: false,
},
},
{ timestamps: true }
);
How to fetch the business with a condition business: isDeleted:false and its reviews with singleReviewSchema: isDeleted:false
I dont know your model names, so please replace path with correct names
but it might look like:
businnesModel.find({isDeleted: false})
.populate({
path: 'reviewModelName',
model: 'review',
populate: {
path: 'reviewArray',
model: 'singleReviewModelName',
match: {
isDeleted : false
}
}
})
It should provide you array of businessModel documents - even when their singleReviews array will be empty (because all of reviews are deleted, or there was zero reviews). So you have to filter it out in JS.
To avoid filtering in JS, and to do it a bit more efficient way for mongodb, you can go with aggregate instead.

How to make sure that only one of two fields are populated in mongoDB

I am using mongoose as an ODM and trying to model an animal/pet. In the model I have 2 fields, parent and shelter. I want to make sure that pet belongs to a person or a shelter but not both. What constraints would allow me to do this.
My model in JS:-
const petSchema = mongoose.Schema({
name: {
type: String,
required: [true, "Pet must have a name."],
trim: true
},
species: {
type: String,
required: [true, "Pet must have a species."]
},
parent: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
shelter: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Shelter'
}
}
I am new to databases and their jargons, correct me if any error in question.
Thank you.
You can use the required function to determine this as follows:
const petSchema = mongoose.Schema({
name: {
type: String,
required: [true, "Pet must have a name."],
trim: true
},
species: {
type: String,
required: [true, "Pet must have a species."]
},
parent: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: function() {
return !this.shelter;
}
},
shelter: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Shelter',
required: function() {
return !this.parent;
}
}
}
I ended up using pre validate middleware in mongoose:-
petSchema.pre('validate', function (next) {
if((this.parent && this.shelter) || (!this.parent && !this.shelter))
return next(new Error("At least and Only one field(parent, shelter) should be populated"))
next()
})

SailsJs/Postgresql - How to create a one way association or one-to-many relation via an unique field

I have two models:
PdfAnnotation.js:
module.exports = {
tableName: "pdf_annotations",
primaryKey: "pk_id",
attributes: {
pk_id: {
type: "number",
autoIncrement: true
},
annotation_id: {
type: "string",
unique: true,
required: true,
},
comments: {
collection: "pdfcomments",
via: "fk_annotation_id"
}
}
};
PdfComments.js:
module.exports = {
tableName: "pdf_comments",
primaryKey: "pk_id",
attributes: {
pk_id: {
type: "number",
autoIncrement: true,
},
fk_annotation_id: {
model: "pdfannotations",
},
comment_content: {
type: "string",
},
}
};
When I run these codes:
PdfAnnotations.create({
annotation_id: "test3",
});
PdfComments.create({
fk_annotation_id: 'test3',
comment_content: 'test',
});
I got this error:
I have followed the documentation: https://sailsjs.com/documentation/concepts/models-and-orm/associations/one-to-many.
The difference between my implementation and the docs is: the constraint I used for PdfComments to PdfAnnotations via an unique field annotation_id(string) not the primary key pk_id(number), so that I got the error.
For some reasons I don't want to use annotation_id as a primary key (such as its type is string)
I'm not familiar with Sails and its ORM, hope to see your help.
Try something like this:
const pdfannotation = await PdfAnnotations.create({
annotation_id: 'test3',
}).fetch();
const pdfcomment = await PdfComments.create({
fk_annotation_id: pdfannotation.id,
comment_content: 'test',
});

ReferenceError: user is not defined in user api

When I open localhost:1337/user I got Internal Server Error
Something isn't right here.
ReferenceError: user is not defined
How can I fix it? My API is not working. I can't insert data in database using html forms in sailsjs.
My user model is:
module.exports = {
attribute: {
firstname: {
type: 'string',
unique: true
},
lastname: {
type: 'string',
unique: true
},
organisationName: {
type: 'string',
unique: true
},
DepatmentName: {
type: 'string',
unique: true
},
DOB: {
type: 'date',
unique: true
},
DOJ: {
type: 'date',
},
DOL: {
type: 'date',
},
Address: {
type: 'string',
},
City: {
type: 'string',
},
State: {
type: 'string',
},
Country: {
type: 'string',
},
email: {
type: 'string',
email: true,
required: true,
unique: true
},
encryptedPassword: {
type: 'string',
},
ContactNumber: {
type: 'integer',
},
//toJSON: function() {
// var obj = this.toObject();
//
// }
}
};
You are calling a variable "user" and it doesn't exist or it's empty. Check youre code for this variable..
In youre usermodel, you only have firstname and lastname. I guess you need one of this. If you want more specific help, then you have to show us some extra coding of the page, not only the model.

Creating custom attributes in Sailsjs

I am trying to create a custom attribute in my sails app and I am not getting any result back in my get call.
My code looks something like this:
module.exports = {
attributes: {
id: {
type: 'string',
primaryKey: true,
defaultsTo: function () {
return uuid.v4();
},
unique: true,
index: true,
uuidv4: true
},
name: {
type: 'string',
required: true
}
fullName: function(){
return this.name ;
}
};
I get back all the fields expect full Name
In my opinion the sailsjs model attributes only create corresponding column and get the column in database based on the type. In your case, the fullName has no type. so it does not know what to get from database.
However, if what you want is the returned json object has some extra fields, you can overwrite the toJSON function to add it.
module.exports={
attributes:
id: {
type: 'string',
primaryKey: true,
defaultsTo: function () {
return uuid.v4();
},
unique: true,
index: true,
uuidv4: true
},
name: {
type: 'string',
required: true
},
toJSON:function(){
var obj=this.toObject();
obj.fullName=obj.name;
return obj;
}
}
}
This issue is a little old, but I've a better answer:
module.exports = {
attributes: {
firstname : 'string',
lastname : 'string,
fullName: function () {
return this.firstname + ' ' + this.lastname
}
toJSON:function(){
var obj = this.toObject();
obj.fullName = this.fullName()
return obj;
}
}
}