Loopback: Using the include filter in hasOne relationship

Created on 6 May 2016  路  16Comments  路  Source: strongloop/loopback

Hi,
I've created a simple has one realtionship between two models (a user and a team ) like this :

    "managedTeam": {
      "type": "hasOne",
      "model": "Team",
      "foreignKey": "ownerId"
    }

The thing is when I use a hasone relationship the api has no "filter" parameter and it doesn't work instead it has a "refresh" parameter.

So if I need to use the api like this via the angular sdk :

User.managedTeam({
          id: uid,
          filter:
          {
            include: ["owner", "members"]
          }
        });

The only way to go is to change the relationship into hasMany to be able to load the team owner and members relations.
Is this really the only way to go?

regards,
Mostafa

feature stale team-apex

Most helpful comment

Any updates on this one?

All 16 comments

So to clarify, you have an owner model and a members model in addition to the user and team model? Can you provide a sample repo? You can fork this sandbox.
https://github.com/strongloop/loopback-sandbox

@0candy So to reproduce my problem it's very simple. you can try to create any simple hasone relation then look at it via the api explorer ... you will see that the get request for it doesn't have a filter parameter.

Here is how it looks like on my end :
fireshot capture 37 - strongloop api__ - http___localhost_3000_explorer_ _

Just to answer your question it's only two models the user model - acting both like team manager and member - and the team model.

user.json

{
  "name": "user",
  "plural": "users",
  "base": "User",
  "properties": {
    "firstName": {
      "type": "string"
    },
    "lastName": {
      "type": "string"
    }
  },
  "validations": [],
  "relations": {
    "accessTokens": {
      "type": "hasMany",
      "model": "accessToken",
      "foreignKey": "userId"
    },
    "identities": {
      "type": "hasMany",
      "model": "userIdentity",
      "foreignKey": "userId"
    },
    "credentials": {
      "type": "hasMany",
      "model": "userCredential",
      "foreignKey": "userId"
    },
    "roles": {
      "type": "hasMany",
      "model": "role",
      "foreignKey": "principalId",
      "through": "roleMapping"
    },
    "visits": {
      "type": "hasMany",
      "model": "Visit",
      "foreignKey": "userId"
    },
    "team": {
      "type": "hasMany",
      "model": "Team",
      "foreignKey": "memberId",
      "through": "TeamMember"
    },
    "managedTeam": {
      "type": "hasOne",
      "model": "Team",
      "foreignKey": "ownerId"
    }
  },
  "acls": [
    {
      "accessType": "*",
      "principalType": "ROLE",
      "principalId": "admin",
      "permission": "ALLOW"
    },
    {
      "accessType": "READ",
      "principalType": "ROLE",
      "principalId": "$unauthenticated",
      "permission": "DENY"
    },
    {
      "accessType": "READ",
      "principalType": "ROLE",
      "principalId": "$authenticated",
      "permission": "ALLOW"
    },
    {
      "accessType": "*",
      "principalType": "ROLE",
      "principalId": "$owner",
      "permission": "ALLOW"
    }
  ],
  "methods": {
    "info": {
      "description": "Get the roles for this user.",
      "isStatic": false,
      "returns": {
        "arg": "result",
        "type": "Object",
        "root": true
      },
      "http": {
        "path": "/info",
        "verb": "get"
      }
    }
  }
}

team.json

{
  "name": "Team",
  "plural": "teams",
  "base": "PersistedModel",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {
    "id": {
      "type": "number",
      "required": true
    },
    "name": {
      "type": "string",
      "required": true
    },
    "ownerId": {
      "type": "number",
      "required": true
    }
  },
  "validations": [],
  "relations": {
    "members": {
      "type": "hasMany",
      "model": "user",
      "foreignKey": "teamId",
      "through": "TeamMember",
      "keyThrough": "memberId"
    },
    "owner": {
      "type": "belongsTo",
      "model": "user",
      "foreignKey": "ownerId"
    }
  },
  "acls": [],
  "methods": {}
}

I hope this helps, and many thanks

Thank you for the info. You are right, hasOne does not take in a filter parameter. We should probably add it for consistency. Would you like to submit a PR?

https://github.com/strongloop/loopback/blob/ca1baee0f9547107bdb54853d49ebce6650a4fbf/lib/model.js#L477

@0candy thanks for clearing this out. I will give a try and see if I can do it.

Any success on implementing that so far?

Any success guys to have this soon? ++++1 @0candy

Unfortunately, we haven't reach this item in our backlog yet as we have some bugs/features to finish to get LB 3.x released. Would you ( @ahmed-abdulmoniem ) be interested in submitting a patch so we can get it in sooner? Thank you for your understanding.

@0candy No problem for sure .. just I would like some guidance .. which part I should change?

For starters, you will need to add the filter arg to accepts: https://github.com/strongloop/loopback/blob/ca1baee0f9547107bdb54853d49ebce6650a4fbf/lib/model.js#L477

@jannyHou Can you point @ahmed-abdulmoniem where he should add the include filter for hasOne in juggler relations?

@jannyHou ?

@ahmed-abdulmoniem I am following the context in this issue, will reply asap :)

@jannyHou Thank you waiting :)

@ahmed-abdulmoniem Let's say we define a hasOne relation from parentModel to childModel, here is the code of function parent.children():
https://github.com/strongloop/loopback-datasource-juggler/blob/master/lib/relation-definition.js#L1640

It doesn't support filter, only returns you the child instance.

I think a possible approach to add filter is define a scope as what hasMany does, see:
https://github.com/strongloop/loopback-datasource-juggler/blob/master/lib/relation-definition.js#L690

A scope property will take a filter parameter, see line 177 in https://github.com/strongloop/loopback-datasource-juggler/blob/master/lib/scope.js#L173-L177

BTW, embedsOne also doesn't support filter. That's out of scope of this story, filed another issue for it: https://github.com/strongloop/loopback-datasource-juggler/issues/1145

@ahmed-abdulmoniem I know that the logic of defining scope method would be a little complicated here, please tell me if anything confuses you :) I am glad to continue the discussion.

cc @raymondfeng

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

This issue has been closed due to continued inactivity. Thank you for your understanding. If you believe this to be in error, please contact one of the code owners, listed in the CODEOWNERS file at the top-level of this repository.

Any updates on this one?

Was this page helpful?
0 / 5 - 0 ratings