5

I would like to filter from REST API by nested data. For example this object:

[
  {
    "name": "Handmade Soft Fish",
    "tags": "Rubber, Rubber, Salad",
    "categories": [
      {
        "name": "women",
        "id": 2,
        "parent_id": 0,
        "permalink": "/women"
      },
      {
        "name": "kids",
        "id": 3,
        "parent_id": 0,
        "permalink": "/kids"
      }
    ]
  },
  {
    "name": "Tasty Rubber Soap",
    "tags": "Granite, Granite, Chair",
    "categories": [
      {
        "name": "kids",
        "id": 3,
        "parent_id": 0,
        "permalink": "/kids"
      }
    ]
  }
]

is comming by GET /api/products?filter[include]=categories and i would like to get only products which has category name "women". How do this?

JanuszO
  • 1,140
  • 12
  • 25

4 Answers4

3

LoopBack does not support filters based on related models.

This is a limitation that we have never had bandwidth to solve, unfortunately :(

For more details, see the discussion and linked issues here:

Miroslav Bajtoš
  • 10,667
  • 1
  • 41
  • 99
1

Maybe you want to get this data by the Category REST API. For example:

GET /api/categories?filter[include]=products&filter[where][name]=woman

The result will be a category object with all products related. To this, will be necessary declare this relation on the models.

Felipe Antero
  • 43
  • 1
  • 7
  • this is a nice idea, but every product object has also other connections, e.g. variants, options, images, etc. Then I am not able to extend the product's properties – JanuszO Nov 28 '18 at 07:53
1
Try like this.It has worked for me.

  const filter = {
          where: {
            'categories.name': {
              inq: ['women']**strong text**
            }
          }
        };

Pass this filter to request as path parameters and the request would be like bellow

GET /api/categoriesfilter=%7B%22where%22:%7B%categories.name%22:%7B%22inq%22:%5B%women%22%5D%7D%7D%7D
  • THIS ACTUALLY WORKS! I struggled for over an hour with things that should have worked, but this is the one that solved the problem. – Kim Jan 31 '22 at 20:47
0

Can you share how it looks like without filter[include]=categorie, please ?

[edit] after a few questions in comment, I'd build a remote method : in common/models/myModel.js (inside the function) :

function getItems(filter, categorieIds = []) {
    return new Promise((resolve, reject) => {
        let newInclude;
        if (filter.hasOwnProperty(include)){
            if (Array.isArray(filter.include)) {
                newInclude = [].concat(filter.include, "categories")
            }else{
                if (filter.include.length > 0) {
                    newInclude = [].concat(filter.include, "categories");
                }else{
                    newInclude = "categories";
                }
            }
        }else{
            newInclude = "categories";
        }

        myModel.find(Object.assign({}, filter, {include: newInclude}))
        .then(data => {
            if (data.length <= 0) return resolve(data);
            if (categoriesIds.length <= 0) return resolve(data);

            // there goes your specific filter on categories
            const tmp = data.filter(
                item => item.categories.findIndex(
                    categorie => categorieIds.indexOf(categorie.id) > -1
                ) > -1
            );
            return resolve(tmp);
        })
    }
}
myModel.remoteMethod('getItems', {
    accepts: [{
        arg: "filter",
        type: "object",
        required: true
    }, {
        arg: "categorieIds",
        type: "array",
        required: true
    }],
    returns: {arg: 'getItems', type: 'array'}
});

I hope it answers your question...

dun32
  • 708
  • 6
  • 9
  • `[{ "name": "Handmade Soft Fish", "tags": "Rubber, Rubber, Salad" }, { "name": "Tasty Rubber Soap", "tags": "Granite, Granite, Chair" }]` looks like this – JanuszO Nov 27 '18 at 08:33
  • Why do you need to do that ? is it for a read only purpose or do you need to build that kind of filter to create / update / delete ? (sorry for my english...) – dun32 Nov 27 '18 at 09:39
  • and what about filter[fields][name]=true&filter[fields][tags]=true&filter[fields][categorieId]=true ? (please, replace categorieId with the name of the relation property) – dun32 Nov 27 '18 at 09:51
  • I need this information on the category page to show products only from a given category. However, "categories" is just an example because in every object I have more properties that also have nested data and I will probably need it in other cases – JanuszO Nov 27 '18 at 10:23
  • it will work for the category, and what with similar cases, when the key is different, the other nesting or working on a different model. There should be something universal, but thank you for your help – JanuszO Nov 27 '18 at 15:00
  • Yes, there should be... Maybe with Loopback 4 ? you welcome – dun32 Nov 27 '18 at 15:30
  • And also, what I do sometimes to read datas from mariadb or MySQL, is to create a view with some joins and apply this view to a loopback model, so that I can filter what I want. But I don't know about the database you're using, and I'm not sure you can apply this Technic to the purpose you want to achieve. It's just another tip... – dun32 Nov 29 '18 at 19:41