Has many through relation, count always returns 0 - loopbackjs

I have a table of companies, a table of addresses and a companiesaddresses table to normalize the many to many relationship. Loopback is working just fine to add a company, add an address to a company and I can even query using the API explorer an address associated with a company using the (POST /Companies/{id}/addresses/{fk}) method.
However, when I try to get all the addresses associated with a company (GET /Companies/{id}/addresses) I get back an empty array. Also when I perform a count on how many addresses a particular company has ( GET /Companies/{id}/addresses/count) I always get 0.
I'm sure I'm missing something really tiny. My datasource is postgresql.
/* ----- common/models/companies.json ----- */
{
"name": "Companies",
"base": "User",
"strict": true,
"idInjection": false,
"options": {
"validateUpsert": true
},
"properties": {
"companyName": {
"type": "string",
"required": true
},
"firstName": {
"type": "string",
"required": true
},
"lastName": {
"type": "string",
"required": true
},
"cellNumber": {
"type": "string"
}
},
"validations": [],
"relations": {
"addresses": {
"type": "hasMany",
"model": "Addresses",
"foreignKey": "addressesid",
"through": "CompaniesAddresses"
}
},
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
},
{
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW",
"property": "create"
},
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW"
},
{
"accessType": "WRITE",
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW"
}
],
"methods": {}
/* ---- common/models/addresses.json ---- */
{
"name": "Addresses",
"base": "PersistedModel",
"strict": true,
"idInjection": false,
"options": {
"validateUpsert": true
},
"properties": {
"streetaddress2": {
"type": "string"
},
"phonenumber2": {
"type": "string"
},
"phonenumber1": {
"type": "string",
"required": true
},
"zippostalcode": {
"type": "string",
"required": true
},
"stateprov": {
"type": "string",
"required": true
},
"streetaddress1": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {
"companies": {
"type": "hasMany",
"model": "Companies",
"foreignKey": "companiesid",
"through": "CompaniesAddresses"
}
},
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
],
"methods": {}
/* ---- companiesaddresses.json ---- */
{
"name": "CompaniesAddresses",
"base": "PersistedModel",
"strict": true,
"idInjection": false,
"options": {
"validateUpsert": true
},
"properties": {
"companiesid": {
"type": "number",
"id": true,
"required": true
},
"addressesid": {
"type": "number",
"id": true,
"required": true
}
},
"validations": [],
"relations": {
"addresses": {
"type": "belongsTo",
"model": "Addresses",
"foreignKey": "addressesid"
},
"companies": {
"type": "belongsTo",
"model": "Companies",
"foreignKey": "companiesid"
}
},
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
],
"methods": {}
}
/* ---- server/boot/model-config.json ---- */
{
"_meta": {
"sources": [
"loopback/common/models",
"loopback/server/models",
"../common/models",
"./models"
],
"mixins": [
"loopback/common/mixins",
"loopback/server/mixins",
"../common/mixins",
"./mixins"
]
},
"User": {
"dataSource": "db"
},
"AccessToken": {
"dataSource": "db",
"public": false
},
"ACL": {
"dataSource": "db",
"public": false
},
"RoleMapping": {
"dataSource": "db",
"public": false
},
"Role": {
"dataSource": "db",
"public": false
},
"Companies": {
"dataSource": "pg",
"public": true,
"$promise": {},
"$resolved": true
},
"Addresses": {
"dataSource": "pg",
"public": true,
"$promise": {},
"$resolved": true
},
"CompaniesAddresses": {
"dataSource": "pg",
"public": true,
"$promise": {},
"$resolved": true
}
}

The foreign keys in companies and addresses are as follows:
**common/models/companies.json**
"relations": {
"addresses": {
"type": "hasMany",
"model": "Addresses",
"foreignKey": "addressesid", <---- this should be companiesid
"through": "CompaniesAddresses"
}
}
On the flip side (addresses) do the same modification, all will work.

Related

loopback.js `POST /foo` isn't offered when using relations

I need a series of endpoints like:
POST /company
POST /company/{id}/customers
POST /company/{id}/customers/{fk}
GET /company/{id}/customers/{fk}
I get #2 and #3 ok, but not number 1 - so, when I try GET /company/{id}/customers/{fk} - it naturally tells me that company id xxx doesn't exist. Yet, the endpoints don't exist.
Below is my configuration if anyone can explain what I am missing
{
"_meta": {
"sources": [
"loopback/common/models",
"loopback/server/models",
"../common/models",
"./models"
],
"mixins": [
"loopback/common/mixins",
"loopback/server/mixins",
"../common/mixins",
"./mixins"
]
},
"customer": {
"dataSource": "memory",
"public": false
},
"company": {
"dataSource": "memory",
"public": true
},
"payment": {
"dataSource": "memory",
"public": false
},
"invoice": {
"dataSource": "memory",
"public": false
},
"integration": {
"dataSource": "memory",
"public": true
}
}
Company model:
{
"name": "company",
"plural": "companies",
"base": "Model",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"id": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {
"customers": {
"type": "hasMany",
"model": "customer",
"foreignKey": "id"
},
"payments": {
"type": "hasMany",
"model": "payment",
"foreignKey": "id"
},
"invoices": {
"type": "hasMany",
"model": "invoice",
"foreignKey": "id"
},
"integration": {
"type": "hasOne",
"model": "integration",
"foreignKey": "companyId",
"primaryKey": "id"
}
},
"acls": [],
"methods": {}
}
Customers (properties removed for brevity sake):
{
"name": "customer",
"plural": "customers",
"base": "Model",
"idInjection": true,
"options": {
"validateUpsert": true
},
"validations": [],
"relations": {
"company": {
"type": "belongsTo",
"model": "company",
"foreignKey": "id",
"primaryKey": "id"
}
},
"acls": [],
"methods": {}
}

Creating a JSON table from 'aws autoscaling describe-auto-scaling-groups'

I have a problem with parsing output/transforming it from aws autoscaling describe-auto-scaling-groups
The output looks like this:
{
"AutoScalingGroups": [
{
"AutoScalingGroupName": "eks-nodegroup-AZ1",
"AutoScalingGroupARN": "arn:aws:autoscaling:eu-central-1::autoScalingGroup:854a8f05-cd3c-421d-abf3-0f3730d0b068:autoScalingGroupName/eks-nodegroup-AZ1",
"LaunchTemplate": {
"LaunchTemplateId": "lt-XXXXXXXXXXXXX",
"LaunchTemplateName": "eks-nodegroup-AZ1",
"Version": "$Latest"
},
"MinSize": 1,
"MaxSize": 6,
"DesiredCapacity": 1,
"DefaultCooldown": 300,
"AvailabilityZones": [
"eu-central-1a"
],
"LoadBalancerNames": [],
"TargetGroupARNs": [],
"HealthCheckType": "EC2",
"HealthCheckGracePeriod": 300,
"Instances": [
{
"InstanceId": "i-XXXXXXXXXXXXXXX",
"AvailabilityZone": "eu-central-1a",
"LifecycleState": "InService",
"HealthStatus": "Healthy",
"LaunchTemplate": {
"LaunchTemplateId": "lt-XXXXXXXXXXXXX",
"LaunchTemplateName": "eks-nodegroup-AZ1",
"Version": "1"
},
"ProtectedFromScaleIn": false
}
],
"CreatedTime": "2019-09-24T17:24:57.805Z",
"SuspendedProcesses": [],
"VPCZoneIdentifier": "subnet-XXXXXXXXXXXX",
"EnabledMetrics": [],
"Tags": [
{
"ResourceId": "eks-nodegroup-AZ1",
"ResourceType": "auto-scaling-group",
"Key": "Name",
"Value": "eks-nodegroup-AZ1",
"PropagateAtLaunch": true
},
{
"ResourceId": "eks-nodegroup-AZ1",
"ResourceType": "auto-scaling-group",
"Key": "k8s.io/cluster-autoscaler/enabled",
"Value": "true",
"PropagateAtLaunch": true
},
{
"ResourceId": "eks-nodegroup-AZ1",
"ResourceType": "auto-scaling-group",
"Key": "k8s.io/cluster-autoscaler/k8s-team-sandbox",
"Value": "true",
"PropagateAtLaunch": true
},
{
"ResourceId": "eks-nodegroup-AZ1",
"ResourceType": "auto-scaling-group",
"Key": "kubernetes.io/cluster/k8s-team-sandbox",
"Value": "owned",
"PropagateAtLaunch": true
}
],
"TerminationPolicies": [
"Default"
],
"NewInstancesProtectedFromScaleIn": false,
"ServiceLinkedRoleARN": "arn:aws:iam::XXXXXXXXXXXXXXX:role/aws-service-role/autoscaling.amazonaws.com/AWSServiceRoleForAutoScaling"
},
{
"AutoScalingGroupName": "eks-k8s-team-sandbox-AZ2",
"AutoScalingGroupARN": "arn:aws:autoscaling:eu-central-1::autoScalingGroup:25324f3a-b911-453c-b316-46657e850b19:autoScalingGroupName/eks-nodegroup-AZ2",
"LaunchTemplate": {
"LaunchTemplateId": "lt-XXXXXXXXXXXX",
"LaunchTemplateName": "eks-nodegroup-AZ2",
"Version": "$Latest"
},
"MinSize": 1,
"MaxSize": 6,
"DesiredCapacity": 1,
"DefaultCooldown": 300,
"AvailabilityZones": [
"eu-central-1b"
],
"LoadBalancerNames": [],
"TargetGroupARNs": [],
"HealthCheckType": "EC2",
"HealthCheckGracePeriod": 300,
"Instances": [
{
"InstanceId": "i-XXXXXXXXXXXX",
"AvailabilityZone": "eu-central-1b",
"LifecycleState": "InService",
"HealthStatus": "Healthy",
"LaunchTemplate": {
"LaunchTemplateId": "lt-XXXXXXXXXX",
"LaunchTemplateName": "eks-nodegroup-AZ2",
"Version": "1"
},
"ProtectedFromScaleIn": false
}
],
"CreatedTime": "2019-09-24T17:24:57.982Z",
"SuspendedProcesses": [],
"VPCZoneIdentifier": "subnet-XXXXXXXX",
"EnabledMetrics": [],
"Tags": [
{
"ResourceId": "eks-nodegroup-AZ2",
"ResourceType": "auto-scaling-group",
"Key": "Name",
"Value": "eks-nodegroup-AZ2",
"PropagateAtLaunch": true
},
{
"ResourceId": "eks-nodegroup-AZ2",
"ResourceType": "auto-scaling-group",
"Key": "k8s.io/cluster-autoscaler/enabled",
"Value": "true",
"PropagateAtLaunch": true
},
{
"ResourceId": "eks-nodegroup-AZ2",
"ResourceType": "auto-scaling-group",
"Key": "k8s.io/cluster-autoscaler/k8s-team-sandbox",
"Value": "true",
"PropagateAtLaunch": true
},
{
"ResourceId": "eks-nodegroup-AZ2",
"ResourceType": "auto-scaling-group",
"Key": "kubernetes.io/cluster/k8s-team-sandbox",
"Value": "owned",
"PropagateAtLaunch": true
}
],
"TerminationPolicies": [
"Default"
],
"NewInstancesProtectedFromScaleIn": false,
"ServiceLinkedRoleARN": "arn:aws:iam::ARN:role/aws-service-role/autoscaling.amazonaws.com/AWSServiceRoleForAutoScaling"
}
]
}
I need to parse it to get :
{
"eks-nodegroup-AZ1" : "$DesiredCapacityForEks-nodegroup-AZ1",
"eks-nodegroup-AZ2" : "$DesiredCapacityForEks-nodegroup-AZ2",
"eks-nodegroup-AZ3" : "$DesiredCapacityForEks-nodegroup-AZ3",
"eks-nodegroup-AZX" : "$DesiredCapacityForEks-nodegroup-AZX",
}
The following expected output will be used for external data resource for terraform to be able to automate DesiredCapacity value during the ASG rolling-updates.
Thanks,
Dominik
Try with your response,
response | jq '.AutoScalingGroups[] | {(.AutoScalingGroupName): .DesiredCapacity}' | jq -s add

Loopback hasManyThrough relation for user

I have such models:
Team
{
"name": "Team",
"plural": "teams",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"mixins": {
"ModelRest": {}
},
"hidden": [
"deleted"
],
"filtered": [
"userId",
"archived"
],
"properties": {
"name": {
"type": "string",
"required": true
},
"createdAt": {
"type": "date"
},
"deleted": {
"type": "boolean"
}
},
"validations": [],
"relations": {
"projects": {
"type": "hasMany",
"model": "Project"
},
"user": {
"type": "belongsTo",
"model": "user"
},
"users": {
"type": "hasMany",
"model": "User",
"foreignKey": "",
"through": "TeamMember"
}
},
"acls": [],
"methods": {}
}
TeamMember
{
"name": "TeamMember",
"plural": "team-members",
"base": "Model",
"idInjection": false,
"options": {
"validateUpsert": true
},
"properties": {},
"validations": [],
"relations": {
"user": {
"type": "belongsTo",
"model": "user"
},
"team": {
"type": "belongsTo",
"model": "Team"
}
},
"acls": [],
"methods": {}
}
user
{
"name": "user",
"plural": "users",
"base": "User",
"idInjection": true,
"mixins": {
"ModelRest": {}
},
"hidden": [
"realm",
"emailVerified",
"lastIP",
"deleted",
"utmSource",
"utmMedium",
"utmCampaign"
],
"readOnly": [
"statusId",
"lastListId",
"teamId",
"subscriptionStart",
"subscriptionExpiration",
"apiKey"
],
"properties": {
"name": {
"type": "string",
"required": true,
"mysql": {
"columnName": "username"
}
},
"password": {
"type": "string",
"required": true,
"min": 5
},
"email": {
"type": "string",
"required": true
},
"createdAt": {
"type": "date"
},
"updatedAt": {
"type": "date"
},
"subscriptionStart": {
"type": "date"
},
"subscriptionExpiration": {
"type": "date"
},
"teamId": {
"type": "number"
},
"sharePlan": {
"type": "boolean"
},
"shareLeads": {
"type": "boolean"
},
"timezone": {
"type": "string"
},
"utmSource": {
"type": "string"
},
"utmMedium": {
"type": "string"
},
"utmCampaign": {
"type": "string"
},
"lastIP": {
"type": "string"
},
"deleted": {
"type": "boolean"
}
},
"validations": [],
"relations": {
"team": {
"type": "belongsTo",
"model": "Team"
},
"plan": {
"type": "belongsTo",
"model": "Plan"
},
"billingCycle": {
"type": "belongsTo",
"model": "BillingCycle"
},
"card": {
"type": "belongsTo",
"model": "Card"
},
"lastList": {
"type": "belongsTo",
"model": "List"
},
"status": {
"type": "belongsTo",
"model": "Status"
},
"accessTokens": {
"type": "hasMany",
"model": "AccessToken"
}
},
"acls": [],
"methods": {}
}
I've created relation in Team model:
"users": {
"type": "hasMany",
"model": "User",
"foreignKey": "",
"through": "TeamMember"
}
But users relation in Team doesn't work at all. In API explorer I see
GET /teams/{id}/user
there is no
GET /teams/{id}/users
Why does this happen?
I've even created this relation with Loopback relation generator. Same result. Can't figure out where is the error. Loopback doest see this relation.
Thanks for any help.
It's all, because in model-config.json I have
"TeamMember": {
"dataSource": null,
"public": true
},
instead of:
"TeamMember": {
"dataSource": "db",
"public": true
},

Remove pk in the loopback swagger

In loopback, how could I remove the PK from the swagger json displayed.
This is the json displayed in my swagger:
{
"user_id": "string",
"order_type": "string",
"date": "2016-04-28",
"payload": {
"id": 0
},
"id": 0
}
image detail- Swagger
how could I remove the "id": 0 ?
This is my order.json :
{
"name": "Order",
"plural": "Orders",
"base": "Model",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"user_id": {
"type": "string",
"required": true
},
"order_type": {
"type": "string",
"required": true
},
"date": {
"type": "date",
"required": true
},
"payload": {
"type": "Payload",
"required": true
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
This is my order.js:
module.exports = (Order) => {
Order.create = function(body, cb) {
//
}
Order.remoteMethod('create', {
'http': {'path': '/'},
'accepts': [
{'arg': 'body', 'type': 'Order', 'required': true, 'http': { 'source': 'body' } }
]
});
};
Hidden property did the trick
{
"name": "Order",
"plural": "Orders",
"base": "Model",
"idInjection": false,
"options": {
"validateUpsert": true
},
"properties": {
...
},
"validations": [],
"relations": {},
"acls": [],
"methods": {},
"hidden": ["id"]
}

Dual belongsTo relations with loopback

I have a couple relations I want to model,
A Message belongs to 2 Profile's (a sender and a recipient)
An Enrollment consists of a Profile and a Curriculum.
I tried to do #1 using 2 hasOne but ended up with Profile.messageId.
{
"name": "Message",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"id": {
"type": "number",
"id": true,
"required": true
},
"text": {
"type": "string",
"required": true
},
"created": {
"type": "date",
"required": true
},
"seen": {
"type": "boolean",
"required": true
}
},
"validations": [],
"relations": {
"sender": {
"type": "hasOne",
"model": "Profile",
"foreignKey": ""
},
"recipient": {
"type": "hasOne",
"model": "Profile",
"foreignKey": ""
}
},
"acls": [],
"methods": []
}
Same problem w/ #2...
{
"name": "Enrollment",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"id": {
"type": "number",
"id": true,
"required": true
},
"created": {
"type": "date",
"required": true
},
"currentPage": {
"type": "string",
"comments": "What page are they on in this curriculum?"
}
},
"validations": [],
"relations": {
"curriculums": {
"type": "hasOne",
"model": "Curriculum",
"foreignKey": ""
},
"profiles": {
"type": "hasOne",
"model": "Profile",
"foreignKey": ""
}
},
"acls": [],
"methods": []
}