In loopback I have defined two models with a double many-to-many relationship as follows:
action.json:
{
"name": "Action",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"text": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {
"benchmark": {
"type": "hasAndBelongsToMany",
"model": "Course",
"foreignKey": "benchmark"
},
"main": {
"type": "hasAndBelongsToMany",
"model": "Course",
"foreignKey": "main"
}
},
"acls": [],
"methods": {}
}
course.json:
{
"name": "Course",
"base": "TrashModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"name": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {
"benchmark": {
"type": "hasAndBelongsToMany",
"model": "Action",
"foreignKey": "benchmark"
},
"main": {
"type": "hasAndBelongsToMany",
"model": "Action",
"foreignKey": "main"
}
},
"acls": [],
"methods": {}
}
Now when I try to create a relation between an action model and a course model with the following PUT request:
http://localhost:3000/api/courses/57331a4eeff440cb02c886ae/benchmark/rel/5731d60da2c6d238e3c3d9b3
Then when I request the course model with the related action models included with the following GET request:
http://localhost:3000/api/courses/57331a4eeff440cb02c886ae?filter=%7B%22include%22%3A%5B%22benchmark%22%2C%22main%22%5D%7D
I get:
{
"name": "Introduction Lessons",
"id": "57331a4eeff440cb02c886ae",
"benchmark": [{
"text": "text here",
"id": "5731d60da2c6d238e3c3d9b3"
}],
"main": [{
"text": "text here",
"id": "5731d60da2c6d238e3c3d9b3"
}]
}
So apparently the action is now attached through both the benchmark as the main relation. How did this happen? Do I setup my models wrong?
From what I understand, when you use hasAndBelongsToMany relashionship, loopback uses a through table which it manages automatically for you.
I believe by default it calls itself From_modelTo_model. In order to have two such relashion you need to tell loopback to manage it differently otherwise they use the same through table.
Try with through option such as
Action
"benchmark": {
"type": "hasAndBelongsToMany",
"model": "Course",
"foreignKey": "benchmark",
"through":"ActionCourseBenchmark"
},
"main": {
"type": "hasAndBelongsToMany",
"model": "Course",
"foreignKey": "main",
"through":"ActionCourseMain"
}
Course
"benchmark": {
"type": "hasAndBelongsToMany",
"model": "Action",
"foreignKey": "benchmark",
"through":"ActionCourseBenchmark"
},
"main": {
"type": "hasAndBelongsToMany",
"model": "Action",
"foreignKey": "main",
"through":"ActionCourseMain"
}
see this github issue for more details
Related
When calling a remote method in my LoopBack project, it seems to only return an empty array. I don't think it is really being called at all but perhaps the default implementation is being called.
member.js
module.exports = function(Member) {
Member.getProjectsForMember = function(id, callback) {
console.error('HERE');
return callback(null, {'test': '123'});
};
};
member.json
{
"name": "member",
"base": "User",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"name": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {
"projects": {
"type": "hasMany",
"model": "project",
"options": {
"nestRemoting": false
}
}
},
"acls": [{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW"
},
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$unauthenticated",
"permission": "DENY"
}
],
"methods": {
"getProjectsForMember": {
"accepts": [{
"arg": "id",
"type": "number",
"required": true,
"http": {
"source": "path"
}
}],
"returns": [{
"arg": "projects",
"type": "Object",
"root": true,
}],
"http": [{
"path": "/:id/projects",
"verb": "get"
}]
}
}
}
I am calling it using the LoopBack API Explorer via a GET to /members/{id}/projects:
http://localhost:3000/api/members/3e26u0aa62155715vcb52afa/projects?access_token=R6GKVHwFuMG2caJexuyoMd0JSNOWtvLVXIEmRj1IkNSrM54bwomQLxHcpqlyFaHk
The response is []. I would expect to see the response of {'test': '123'} and the 'HERE' logged to the terminal but I do not.
I have used an "include" : "organization" query in the scope of my request.json file, which is a related model. But, the relation is not being included in the resulting output from a query.
The model (request.json file) looks like...
{
"name": "request",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"amount": {
"type": "number",
"required": true
},
"deadline": {
"type": "date",
"required": true
}
},
"validations": [],
"relations": {
"organization": {
"type": "belongsTo",
"model": "organization",
"foreignKey": "",
"options": {
"nestRemoting": true
}
}
},
"scope" : {
"include" : "organization"
}
}
In order to include another model, you must have a foreignKey defined in your model relations.
"relations": {
"organization": {
"type": "belongsTo",
"model": "organization",
"foreignKey": "organizationId",
"options": {
"nestRemoting": true
}
}
},
set the name of the foreignKey that you want to use. organizationId in this case, and this field will be added to your model request
I want to test my Web API with a postman on the javascript app.
I have the following swagger.
"/attachment/erase": {
"post": {
"summary": "Erase ",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"parameters": [
{
"name": "folder",
"in": "query",
"type": "string",
"description": "folder('s) detail",
"required": true
},
{
"name": "type",
"in": "query",
"type": "string",
"description": "ABC or BCD",
"required": true
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"type": "object",
"required": ["files"],
"properties": {
"attachments": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"description": "The file(s) to delete"
}
],
"responses": {
"200": {
"description": "file(s) erased."
}
}
}
}
So I send the following request :
with the following body :
In return, I get an error 415.
What I am doing wrong?
You're sending x-www-form-urlencoded when the API is expecting application/json.
How about passing a form-data parameter file, please refer the image
I am trying to query my data the following way:
const filter = {where: {activity_id: activity_id, include: {relation: 'planGoal', scope: {where: {activity_goal_id: goal_id}}}}};
However this doesn't seem to work only the activity_id filter is applied and the wrong data is returned.
So my question is how do I query data within an include? and is it even possible?
For reference, here are the models in question:
{
"name": "plan_goal_has_action_option",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"id": {
"type": "number"
},
"activity_id": {
"type": "number"
},
"plan_has_goal_id": {
"type": "number"
},
"action_option": {
"type": "string"
}
},
"validations": [],
"relations": {
"planGoal": {
"type": "belongsTo",
"model": "plan_has_goal",
"foreignKey": "plan_has_goal_id"
}
},
"acls": [],
"methods": {}
}
{
"name": "plan_has_goal",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"id": {
"type": "number"
},
"activity_id": {
"type": "number"
},
"activity_goal_id": {
"type": "number"
}
},
"validations": [],
"relations": {
"goal": {
"type": "belongsTo",
"model": "activity_goal",
"foreignKey": "activity_goal_id"
},
"actions": {
"type": "hasMany",
"model": "plan_goal_has_action_option",
"foreignKey": "plan_has_goal_id"
}
},
"acls": [],
"methods": {}
}
include and where are two different filters:
{
where: {
activity_id: activity_id
},
include: {
relation: 'planGoal',
scope: {
where: {
activity_goal_id: goal_id
}
}
}
}
in loopback, I started with this model:
[
{
"mov_id": 0,
"mov_tipo": "string",
"mov_valore": 0,
"mov_causale_fk": 0,
"mov_conto_fk": 0,
"mov_data": "2017-10-04T09:02:19.620Z",
"mov_note": "string",
"mov_utente_fk": 0,
"mov_aggiunta": "2017-10-04T09:02:19.620Z"
}
]
then I added two relations, which correspond to two Foreign Keys in my MySQL database:
"relations": {
"causale_fk": {
"type": "hasOne",
"model": "causali",
"foreignKey": "causale_id",
"options": {
"nestRemoting": true
}
},
"conto_fk": {
"type": "hasOne",
"model": "conti",
"foreignKey": "conto_id",
"options": {
"nestRemoting": true
}
}
},
I would also like to see the fields in those models, as if I did make a query with JOIN.
it's possible??
ok, i resolved with scope.
this is the model:
{
"name": "movimenti",
"plural": "movimenti",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"scope": {
"include": [
"causale_fk",
"conto_fk"
]
},
"properties": {
"mov_id": {
"type": "number",
"id": true,
"required": true
},
"mov_valore": {
"type": "number",
"required": true
}
},
"validations": [],
"relations": {
"causale_fk": {
"type": "hasOne",
"model": "causali",
"foreignKey": "causale_id"
},
"conto_fk": {
"type": "hasOne",
"model": "conti",
"foreignKey": "conto_id",
"include": "conti"
}
},
"acls": [],
"methods": {}
}
bye!!
You can your to add options in your filter, and the particular option you need to set is include. Check here for more details.
This is an example for you particular needs:
{
Model.find({include:['causale_fk','conto_fk']}, function(){});
}