Multiple include model in loopback - node.js

Hi, im using loopback 3, and i need to do this query:
select nbd.Comment.id as commentId,
nbd.Comment.content as commentConted,
commentCreator.id as userCommentId,
commentCreator.username userComment,
reply.id as replyId,
reply.content as replyContent,
replyCreator.id as replyUserId,
replyCreator.username as replyUser
from nbd.Comment
inner join nbd.User commentCreator on (nbd.Comment.userId =
commentCreator.id)
left join nbd.Comment reply on (nbd.Comment.commentParentId =
reply.commentParentId)
left join nbd.User replyCreator on (reply.userId = replyCreator.id)
So, to do that, i used this include filter:
{
"include": {
"relation": "user",
"scope": {
"fields": [
"id",
"username"
]
},
"relation1": "comments",
"scope1": {
"include": [
"user"
]
}
}
}
But, it doesn't work...
Here is the context, a comment is created by a user, also the comment can have a reply that also is created by a user.
This is the comment model relations:
"relations": {
"user": {
"type": "belongsTo",
"model": "MyUser",
"foreignKey": "userId"
},
"comment": {
"type": "belongsTo",
"model": "Comment",
"foreignKey": "commentParentId"
},
"comments": {
"type": "hasMany",
"model": "Comment",
"foreignKey": "commentParentId"
}
And this is my-user model relation with comments:
"relations": {
"comments": {
"type": "hasMany",
"model": "Comment",
"foreignKey": "userId"
}
}

the solution is simple, if some one want to to a similar query or multiple includes in the same level with loopback, here is and example:
{
"where": {
"field": 1
},
"order": "field DESC",
"include": [
{
"relation": "relation1",
"scope": {
"fields": [
"field1",
"field2",
"field3"
],
"where": {
"field2": {
"gt": 2
}
}
}
},
{
"relation": "relation2",
"scope": {
"fields": [
"field1",
"field2",
"field3",
"field4"
]
}
}
]
}
With these structure is possible to generate multiples includes, the most important aspect on queries with includes are the relations, the relations have to be well defined.

Related

Filter by Product Properties with Store API

For the store API endpoint /store-api/product is it possible to filter on the properties of a product? Not the defaults such as whether it's active or stock levels, but the properties we've defined on the product, for example colour or farbe? For the search endpoint it supports passing in a list of properties ID's which this one does not.
None of the below queries work, and return the various errors below or Call to a member function buildAccessor() on null.
{
"limit": 40,
"filter": [
{
"type": "contains",
"field": "Farbe",
"value": "red"
}
]
}
"Field \"Farbe\" in entity \"product\" was not found."
{
"limit": 40,
"filter": [
{
"type": "contains",
"field": "properties.Farbe",
"value": "red"
}
]
}
"Field \"Farbe\" in entity \"property_group_option\" was not found."
You can combine filters for the name of the property value and their respective group in a multi filter. The following example will only give you products that have the "shoe-color" property with the value "coral".
{
"limit": 1,
"includes": {
"product": ["id", "productNumber", "properties"],
"property_group_option": ["name", "group"],
"property_group": ["name"]
},
"associations": {
"properties": {
"associations": {
"group": []
}
}
},
"filter": [
{
"type": "multi",
"operator": "and",
"queries": [
{
"type": "equals",
"field": "properties.group.name",
"value": "shoe-color"
},
{
"type": "equals",
"field": "properties.name",
"value": "coral"
}
]
}
]
}
Example response:
{
"entity": "product",
"total": 1,
"aggregations": [],
"page": 1,
"limit": 1,
"elements": [
{
"productNumber": "6bbfe1f608504c9b9a7bf92d6a071734",
"properties": [
{
"name": "coral",
"group": {
"name": "shoe-color",
"apiAlias": "property_group"
},
"apiAlias": "property_group_option"
},
{
"name": "cotton",
"group": {
"name": "textile",
"apiAlias": "property_group"
},
"apiAlias": "property_group_option"
}
],
"id": "062ba988aa1840fa84371c9c43b2f838",
"apiAlias": "product"
}
],
"states": [],
"apiAlias": "dal_entity_search_result"
}

Two relations from same model loopback not working

I have two models users and appointments.
The users model is like below-
{
"users": {
"0": {
"id": "1",
"name": "test1",
"role": "doctor"
},
"1": {
"id": "2",
"name": "test2",
"role": "patient"
},
"2": {
"id": "3",
"name": "test3",
"role": "support"
}
}
}
Now in the above model , if the role is doctor , we are calling it as doctor_id , if patient then patient_id and so on.
Now my appointment model is below->
{
"name": "appointments",
"plural": "appointments",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"appointmentDate": {
"type": "date"
},
"appointmentTime": {
"type": "string"
},
"doctorId": {
"type": "string"
},
"patientId": {
"type": "string"
}
},
"validations": [],
"relations": {
"Doctor": {
"type": "belongsTo",
"model": "users",
"foreignKey": "doctorId"
},
"Patient": {
"type": "belongsTo",
"model": "users",
"foreignKey": "patientId"
}
},
"acls": [],
"methods": {}
}
So when i try to GET all appointments , it is not sending the relation data from users. If i add single relation it work as expected , but not working with multiple relations from same model.
Thanks in advance,
Including my previous comment to give context:
The way I did it, I believe foreignkey should be "" for both. You should not define doctorId and patientId and you probably have to define two hasMany relations in you user class with foreign key "Doctor" and "Patient"
To give an example here are the relations defined in my user class (called customer)
"commentsWritten": {
"type": "hasMany",
"model": "comment",
"foreignKey": "sourceCustomerId"
},
"commentsReceived": {
"type": "hasMany",
"model": "comment",
"foreignKey": "targetCustomerId"
},
then in my comment definition I have the following
"properties": {
...
"targetCustomerId": {
"type": {
"required": true
}
},
"sourceCustomerId": {
"type": {
"required": true
}
}
},
"relations": {
"targetCustomer": {
"type": "belongsTo",
"model": "customer",
"foreignKey": ""
},
"sourceCustomer": {
"type": "belongsTo",
"model": "customer",
"foreignKey": ""
}
},
Please note, that I did define the properties (ids) but, if I remember correctly, it was only so I could force them to be not null, i.e. you should not need it.
If you go to the belongsTo documentation you can see that the foreignKey field is empty, so you need to remove it from your relations definition.
You probably also want to define the other side of the relation.
I.e. define a hasMany relation users hasMany appointments:
{
"name": "users",
"base": "PersistedModel",
...
"relations": {
"doctors": {
"type": "hasMany",
"model": "appointments",
"foreignKey": "doctorId"
},
"patients": {
"type": "hasMany",
"model": "appointments",
"foreignKey": "patientId"
},
...
}
However, what you are trying to do might not be supported (and in fact I'm not even sure if it makes sense for LoopBack).
You can check the documentation on polymorphic relations and even though it's a work in progress there's no mention of having Model A hasMany Model B through more than one foreignKey at the same time.
LoopBack would need to have some logic to search under the first foreign key and if nothing is found then searching under the other foreign key, and I'm not sure if this complex composition is supported.
Suggestion
Why not define two models, one for Doctors and one for Patients and have two different relations instead? You can even go to the documentation on HasManyThrough relations and you can see an example that models something very similar to what you are trying to do.

loopback relation to same model

I have a FollowMap as follows
{
"name": "FollowMap",
.
.
.
"relations": {
"follower_acc": {
"type": "belongsTo",
"model": "Account",
"foreignKey": "follower_id"
},
"following_acc": {
"type": "belongsTo",
"model": "Account",
"foreignKey": "following_id"
}
}
}
I want to build a relation to my Account model, so I can get one users follower & following list, the Account model is as follows;
{
"name": "Account",
.
.
.
"followers": {
"type": "hasMany",
"model": "FollowMap",
"foreignKey": "following_id"
},
"following": {
"type": "hasMany",
"model": "FollowMap",
"foreignKey": "follower_id"
}
}
}
From the relation, I can fetch a Account's follower and following count however, I can't fetch the follower and following Account list from these relations. I hope it's clear.
I know this issue is maybe outdated, but for those who are still looking for the solution, i'll give mine. I wanted to do implement the publisher/subscriber relation between the profils entities in my database.
The most obvious way to do it is with the hasAndBelongsToMany relation, but strangely you cannot change the foreignKey used in model: it means you cannot declare "publishedId" and "subscriberId" to be used as foreign keys referencing a Profil entity.
You have to declare manually the third table used to reference those 2 foreign keys.
My working example for this third table:
//common/models/subscribing.json
{
"name": "Subscribing",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {},
"validations": [],
"relations": {
"subscriber": {
"type": "belongsTo",
"model": "Profil",
"as": "subscriber"
},
"publisher": {
"type": "belongsTo",
"model": "Profil",
"as": "publisher"
}
},
"acls": [],
"methods": {}
}
And my Profil entity related to itself through the Subscribings table:
//common/models/profil.json
{
"name": "Profil",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"name": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {
"followers": {
"type": "hasMany",
"model": "Profil",
"foreignKey": "publisherId",
"keyThrough": "subscriberId",
"through": "Subscribing"
},
"subscribings": {
"type": "hasMany",
"model": "Profil",
"foreignKey": "subscriberId",
"keyThrough": "publisherId",
"through": "Subscribing"
}
},
"acls": [],
"methods": {}
}

Include sub model in related model in loopback

I have Account model which hasMany Posts, and Post belongsTo Account
Account:
{
"name": "Account",
"base": "User",
"relations": {
"post": {
"type": "hasMany",
"model": "Post",
"foreignKey": "accountId"
},
...
},
...
}
Post:
{
"name": "Post",
"base": "PersistedModel",
"relations": {
"account": {
"type": "belongsTo",
"model": "Account",
"foreignKey": ""
}
},
...
}
Now, I have model Question which is sub model of Post model.
{
"name": "Question",
"base": "Post", ...
}
I want to query for specific Account all his fields and to include all his Questions with something like this
Account.findById({
id: id,
filter: {include: 'question'},
function(){...});
Is it possible?
Account.findById(id, { include: { relation: 'questions' } }, function(){...});
You may need to create a questions relationship in the Account model, as I don't think it will inherit those from your Post model.
Note also that you should probably rename the post relationship to posts. So your relations section should look like:
Account:
{
"name": "Account",
"base": "User",
"relations": {
"posts": {
"type": "hasMany",
"model": "Post",
"foreignKey": "accountId"
},
"questions": {
"type": "hasMany",
"model": "Question",
"foreignKey": "accountId"
}
...
},
...
}

Complicated relationship with 2 Thorough Models

I have complicated relationship that includes 2 thorough models. I want to create custom method that solves my purpose. I have MySQL DB as datasouce.
3 Main Models.
Artist, Album, Songs.
Album and Song are related 2 each other with N:N relationship through model "Tracklist". Artist and Tracklist are connected through thorough model "TracklistArtist".
I wish to get list of albums and songs of particular artist through this relationship. Though I achieved with patches but it returns duplicate list and same time I want unique record list. Please help.
I am just mentioning Model relation object here instead of complete model-object.
artist.json
{
"name": "Artist",
"relations": {
"tracklists": {
"type": "hasMany",
"model": "Tracklist",
"foreignKey": "",
"through": "TracklistArtist"
}
}
}
album.json
{
"name" : "Album",
"relations": {
"songs": {
"type": "hasMany",
"model": "Song",
"foreignKey": "",
"through": "Tracklist"
}
}
}
song.json
{
"name" : "Song",
"relations": {
"albums": {
"type": "hasMany",
"model": "Album",
"foreignKey": "",
"through": "Tracklist"
}
}
}
tracklist.json
{
"name": "Tracklist",
"relations": {
"album": {
"type": "belongsTo",
"model": "Album",
"foreignKey": ""
},
"song": {
"type": "belongsTo",
"model": "Song",
"foreignKey": ""
},
"artists": {
"type": "hasMany",
"model": "Artist",
"foreignKey": "",
"through": "TracklistArtist"
}
}
}
tracklist-artist.json
{
"name": "TracklistArtist",
"relations": {
"artist": {
"type": "belongsTo",
"model": "Artist",
"foreignKey": ""
},
"tracklist": {
"type": "belongsTo",
"model": "Tracklist",
"foreignKey": ""
}
}
}
I have checked patched from mysql-connector of loopback. Here is link. Check Here
Artist.tracklists({
id: $stateParams.artistId,
filter: {
groupBY:"albumId",
include: {relation: "album", scope: {}},
}
}).$promise.then(function (data) {
});
You propably will need to chain your include to get every relations with something like:
Artist.find({
include: {
relation: 'Tracklist',
scope: {
include: {
relation: ['Album', 'Song']
}
}
},
where: {id: 12345}
}, function() { ... });
Edit:
Artist.find({
include: {
relation: 'Tracklist',
scope: {
include: {
relation: ['Album']
},
scope: {
include: {
relation: 'Tracklist',
scope: {
include: {
relation: ['Song']
}
}
}
}
},
where: {id: 12345}
}, function() { ... });

Resources