简体   繁体   中英

Strongloop Loopback: Filter by id of related Model

I have a Strongloop Loopback Node.js project with some models and relations.

The problem at hand

My problem relates how to query only those Media instances that have a relation to a certain Tag id, using the Angular SDK - while not querying Tags.media (which return Tag instances), but instead making a query somehow that returns plain Media instances.

Please read below for specific information..

Spec

Basically, I have a Model Media which has many 'tags' (model Tag ). Think of a image file ( Media ) having various EXIF tags ( Tag ). Here is the relation spec (this all works as expected):

Media (media.json):

{
  "name": "media",
  "base": "PersistedModel",
  "properties": {
    "id": {
      "type": "string",
      "id": true
    }
  },
  "relations": {
    "tags": {
      "type": "hasAndBelongsToMany",
      "model": "tag"
    }
}

Tag (tag.json):

{
  "name": "tag",
  "base": "PersistedModel",
  "idInjection": true,
  "properties": {
    "name": {
      "type": "string",
      "required": true
    }
  },
  "relations": {
    "medias": {
      "type": "hasAndBelongsToMany",
      "model": "media"
    }
  },
  "acls": [],
  "methods": []
}

Solutions

Now, I know I could do a query like this (using Angular SDK in my example, but the syntax is the same):

injector.get('Tag').find({
  'filter': {
    'include': 'medias',
    'where': {'id': <mytagid>}
  }
});

My problem with this approach is, that I receive 1 ( one ) Tag instance with attached Media instances. This disrupts why whole workflow as I deal only with Media instances.. i just want to filter by Tag id, not bother about Tag at all.

Bottom line

If I see the API explorer ( /explorer/ ), the return value of GET /api/tags/<myTagID>/medias is exactly what I need - an array of Media objects - but how to query them exactly like this using the Angular SDK (lb_services)?

I had a similar problem. One recommendation is to open the lb-services.js and try to find: /tags/:id/medias or something similar. Then you will find a comment like this: // INTERNAL. Use Tags.medias() instead. Or something similar. So that is the method that you should call. Do not call the "prototype$__get....." methods.

Then just call what it says there I suppose: Tag.medias({id:})

Other suggestions:

As you said in your description Media has many Tags. So why not use just

{
  "name": "media",
  "base": "PersistedModel",
  "properties": {
    "id": {
      "type": "string",
      "id": true
    }
  },
  "relations": {
    "tags": {
      "type": "hasMany",   <---------- hasMany
      "model": "tag",
      "foreignKey": "tagId" <---FK name
    }
  }

and for the tags just belongsTo as type.

{
  "name": "tag",
  "base": "PersistedModel",
  "idInjection": true,
  "properties": {
    "name": {
      "type": "string",
      "required": true
    }
  },
  "relations": {
    "medias": {
      "type": "belongsTo",
      "model": "media",
      "foreignKey": "mediaId"  <---FK name
    }
  },
  "acls": [],
  "methods": []
}

But really I don't think this is the problem because you said when you request GET /api/tags/<myTagID>/medias it returns what you want.

Then, in AngularJS you can use:

 Media.tags({id:<mediaId>})

for media/:id/tags

and for the other side try:

Tag.medias({id:<tagId>})


Tag.find({
       filter:{
          where:{mediaId: <mediaId>}     <----mediaId comes from FK name    
       }
   })

In this case both are persistent models there is no problems, I had permission problems when doing a similar thing with data that extends User type. But that is another story...

Hope this is helpful, I changed some stuff from a similar app that I am doing and hope not making so many errors when adapting to your code...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM