Sails.js Query project by relationship

I am running sails 0.10.5

with postgresql support and I want to ask if there is a way to make a query to filter the results by relationship. For example:

http://api/documents?user.role=Admin

      

or

http://api/documents?where={"user.role": "Admin"}

      

or

http://api/documents?where={"user.role": {"like": "%Admin%"}}

      

If the Document model is related to a relationship with a User that has an attribute called role (string fe).

I was unable to fulfill such a request, am I missing something?

Thank!

+3


source to share


2 answers


I don't think this is possible with SailsJS 0.10.5. Actually I would like to do the same, so I decided to do a quick hack for this purpose.

Open the file sails/lib/hooks/blueprints/actionUtil.js

, edit the method populateEach

as shown below:

populateEach: function ( query, req ) {
    var DEFAULT_POPULATE_LIMIT = sails.config.blueprints.defaultLimit || 30;
    var _options = req.options;
    var aliasFilter = req.param('populate');
    var shouldPopulate = _options.populate;

    // Convert the string representation of the filter list to an Array. We
    // need this to provide flexibility in the request param. This way both
    // list string representations are supported:
    //   /model?populate=alias1,alias2,alias3
    //   /model?populate=[alias1,alias2,alias3]
    if (typeof aliasFilter === 'string') {
        aliasFilter = aliasFilter.replace(/\[|\]/g, '');
        aliasFilter = (aliasFilter) ? aliasFilter.split(',') : [];
    }

    return _(_options.associations).reduce(function populateEachAssociation (query, association) {        
        // If an alias filter was provided, override the blueprint config.
        if (aliasFilter) {
            shouldPopulate = _.contains(aliasFilter, association.alias);
        }

        // Only populate associations if a population filter has been supplied
        // with the request or if `populate` is set within the blueprint config.
        // Population filters will override any value stored in the config.
        //
        // Additionally, allow an object to be specified, where the key is the
        // name of the association attribute, and value is true/false
        // (true to populate, false to not)
        if (shouldPopulate) {
            // IMPORTANT NOTE: This is my trick. We should take advanced options from request parameter to make requests even more flexible
            var populationOptions = req.param('populate_' + association.alias);

            if (!populationOptions) {
                var populationLimit = _options['populate_' + association.alias+'_limit'] ||
                                      _options.populate_limit ||
                                      _options.limit ||
                                      DEFAULT_POPULATE_LIMIT;
                populationOptions = {limit: populationLimit};
            }

            return query.populate(association.alias, populationOptions);
        }
        else { 
            return query;
        }
    }, query);
},

      

Hooray! Your API can now handle additional association filters as shown below:



# POST /api/documents
{
    "where" : {
        // Normal conditions
    }
    "populate_user": {
        // Advanced condition for association 'admin'
        "where" : {
            "role" : {
                 "like": "%Admin%"
            }
        },
        "limit" : 4    
     }
}

      

I hope this helps. By the way, I'll take the time to submit a request to port this improvement to core SailsJS tomorrow.

P / S: The core of SailsJS is pretty well done. The main committers are probably too busy to handle all feature requests. Contribution!

+1


source


It seems that "population" works fine in sails v0.12. I tested it for 1st level - associations and works great. But so far, it has not been possible to get an acceptable and reliable method of obtaining only dominant model records that met certain criteria in deep associations -> this was the original question or even at the 2nd or 3rd level. Writing custom controllers is the only way at the moment, or a client revision with more logic to handle this kind of "reverse" lookup, that's how it's done at the moment.

First, I find a related model that meets the required criteria, and then from that set, I pull out the "great" dominant record IDs. This usually means at least one or two requests per server / tier, because the last request has an OR array of dominant model IDs.



Also, making POST requests to some URL to get data is not such a great idea because it breaks the core of REST principles: https://spring.io/understanding/REST

0


source







All Articles