Loopback : One model having multiple relations with other models - loopbackjs

Use Case
An Organisation has many leave types.
An Employee of the Organisation has many Leaves.
A Leave has a single leave type.
So, as an employee when I apply for a leave, the leave should conform to the LeaveType that has been defined by the Organisation.
Problem
The LeaveType model has a 'Belongs to' relationship with both Leave and Organisation models and hence does not behave as intended.
Relations
These are the relations defined in the model.json file.
LeaveType
"organization": {
"type": "belongsTo",
"model": "Organization",
"foreignKey": ""
},
"leave": {
"type": "belongsTo",
"model": "Leave",
"foreignKey": ""
}
Organisation
"leaveTypes": {
"type": "hasMany",
"model": "LeaveType",
"foreignKey": ""
}
Leave
"employee": {
"type": "belongsTo",
"model": "Employee",
"foreignKey": ""
},
"leaveType": {
"type": "hasOne",
"model": "LeaveType",
"foreignKey": ""
}
P.S: I'm using mongoDB for persistence.

Related

Avro schema is not valid

I am trying to save this Avro schema. I get the message that the schema is not valid. Can someone share why its not valid?
{
"type": "record",
"name": "Interactions",
"namespace": "com.amazonaws.personalize.schema",
"fields": [
{
"name": "InvoiceNo",
"type": "int"
},
{
"name": "StockCode",
"type": "int"
},
{
"name": "Description",
"type": "long"
},
{
"name": "Quantity",
"type": "string"
},
{
"name": "InvoiceDate",
"type": "string"
},
{
"name": "UnitPrice",
"type": "string"
},
{
"name": "CustomerID",
"type": "string"
},
{
"name": "CustomerID",
"type": "string"
},
{
"name": "Country",
"type": "string"
}
],
"version": "1.0"
}
I'm a bit late to the party here but I think your issue is twofold.
(1) You haven't reformatted your columns to use the field names that Personalize want to see. Required fields for Interactions are USER_ID, ITEM_ID, and TIMESTAMP. (With TIMESTAMP being in Unix Epoch format.) See reference here.
(2) The five specified fields for Interactions are USER_ID, ITEM_ID, TIMESTAMP, EVENT_TYPE, and EVENT_VALUE. If you do include more fields, they will be considered metadata fields and you can only include up to 5 metadata fields. If you do include them AND the data type is "String" you, they must be specified as "categorical". See page 35 of the Personalize Developer's Guide for an example.
Hope this helps!

I am using loopback 3 and idInjection false is not working

My database is in PostgreSQL.My model defination is as below -
{
"name": "City",
"base": "PersistedModel",
"idInjection": false,
"options": {
"validateUpsert": true
},
"properties": {
"name": {
"type": "string"
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
I am using code below to auto update the tables but when I go to database after running the code below and I check fields, I see id field created with an auto increment. How can I prevent creation of "id" field ?
ds.autoupdate("City", function (er) {
if (er) throw err
});
How can I prevent creation of "id" field?
If you're using a database, you can't. See this issue.
A model without any id properties can only be used without attaching to a database.
Making the name property an Id looks like the only way to use it with a relational database.
"name": {
"type": "string",
"id": 1
}

loopback 2 - defining an array of objects on a model

if I have a usermodel and I define:
"events": {
"type": [
"Object"
]
},
Do I need to define anything else in the usermodel.js to be able to post things like: [{name: 'sample', ...}, ...] to the user table's events column?
I ask because if I remove this particular definition from the .json the app compiles and the database migrates, but with it in, the app compiles but the database states there was an issue with the users findByid. My debugging has narrowed it down to this particular set of code.
I think you can simply use this structure
{
"events":{
"type": [
{
"key": "type",
"key2": "type"
}
]
}
}
You can see a .js example here and .json example here.
but I can also see an issue with the implementation here that says
this model has problem. When we fetch the data with any get call, it
renders this particular field as ["Object Object"] even though the
data is properly saved in the database.
which I would recommend you to try on your own as it will depend a lot on versions and drivers.
Though I would like to ask that what kind of database are you using?
Another way would be to define the object you want in the array as a model, then use that model as your type:
Model: Class
{
"name": "Class",
"base": "Model",
"strict": true,
"idInjection": false,
"properties": {
"label": {
"type": "string",
"required": true
}
}
}
Model: Student
{
"name": "Student",
"base": "PersistedModel",
"strict": true,
"idInjection": true,
"properties": {
"classes": {
"type": ["Class"],
"required": false
},
}
}

Can a PersistedModel relation name be the same as the property name?

In the Loopback documentation relations always have different names than the property they are stored in. For example:
{
"name": "Customer",
"base": "PersistedModel",
"idInjection": true,
"properties": {
"name": {
"type": "string"
}
},
"relations": {
"address": {
"type": "embedsOne",
"model": "Address",
"property": "billingAddress",
"options": {
"validate": true,
"forceId": false
}
}
...
}
Note in this case the address relation has a property of billingAddress. Things seem to break when we use a property of address as instead.
Sometimes its hard to come up with an arbitrary adjective to prepend to the property. For example, say the relation was to a model already called BillingAddress instead of Address. It would be natural to want to name both the relation and the property billingAddress.
For example:
{
"name": "Customer",
"base": "PersistedModel",
"idInjection": true,
"properties": {
"name": {
"type": "string"
}
},
"relations": {
"billingAddress": {
"type": "embedsOne",
"model": "BillingAddress",
"property": "billingAddress",
"options": {
"validate": true,
"forceId": false
}
}
...
}
How do you handle this situation in Loopback?
With the current state of loopback, I believe it's a bad idea. I tried it a few times on different types of relationships having the same reasons you came up with, in most cases it breaks something if it works. Looking at the documentation and loopback I can tell relationships were designed in a way that relation name and the property must be different, even if it works, it might break in the future.
For these things I would add a postfix to the relation name, for example billingAddressDetails or billingAddressRelation.
In the mean time you could also open an issue in github, but I think things will stay the same way in the future.

Validate uniqueness of combination of multiple fields of a model in loopback

How to ensure uniqueness of a combination of multiple fields in loopback model. Like below is the model Organisation, I have two field name and contact in it, I want the combination of these two fields to be unique in the database.
For example :- while creating an organisation two records can have same value in the 'name' field but the combination of the value of the 'name' and the 'contact' field should be unique for each record in order to create it.
`{
"name": "Organisation",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"name": {
"type": "string",
"required": true
},
"contact": {
"type": "number",
"required": true
}
}`
You can use indexes for this purpose. Check documentation, there are several very good examples that covers this topic.
"nameContactUniqueIndex": {
"keys": {
"name": 1,
"contact": -1
},
"options": {
"unique": true
}
}
A key value of 1 specifies ascending order, and -1 specifies descending order.