2014-12-03 3 views
3

Я использую паруса 0.10.5 с поддержкой postgresql, и я хочу спросить, есть ли способ сделать запрос для фильтрации результатов по отношениям. Например:sails.js запрос Blueprint по отношениям

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

Или

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

Или

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

Если модель документа имеет отношение к belongsTo пользователя, который имеет атрибут роль (строка F.E.).

Я не смог выполнить такой запрос, я что-то упустил?

Спасибо!

ответ

1

Я не думаю, что это возможно с SailsJS 0.10.5. На самом деле я хотел бы сделать то же самое, поэтому я решил сделать быстрый взлом для этой цели.

Открыть файл sails/lib/hooks/blueprints/actionUtil.js, редактировать метод populateEach, как показано ниже:

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); 
}, 

Yay! Теперь ваш API может обрабатывать дополнительные фильтры ассоциации, как показано ниже:

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

Я надеюсь, что это поможет. Кстати, я найду время, чтобы отправить запрос на повышение этого улучшения на ядро ​​SailsJS завтра.

P/S: Ядро SailsJS довольно хорошо сделано. Вероятно, основные коммиттеры слишком заняты, чтобы обрабатывать все запросы функций. Давайте вносить свой вклад!

+0

Hi Ducky, спасибо за ваш ответ, но я не могу заставить его работать. Когда я делаю то, что вы предлагаете, я всегда получаю «Детали: ошибка: column document.populate_user не существует». Кроме того, я думал о более общем решении. Там, где вы можете перемещаться по дереву отношений, используя точечную нотацию. Я не знаю, объясню ли я это хорошо. =/ – Drakson

+0

Не могли бы вы дать мне более подробную информацию о том, как вы делаете запрос? Это решение работает для меня до сих пор. Btw, если GET не работает, попробуйте вместо этого POST (jus in case) – Ducky

+0

Это должен быть запрос GET. Моя просьба: 'http: // api/documents?populate_user = {где: {role: 'Admin'}} ' – Drakson

0

Кажется, «население» отлично работает в парусах v0.12. Я тестировал его для 1-го уровня - ассоциации и отлично работает. Но до сих пор не удалось получить приемлемый и надежный метод получения только доминирующих записей моделей, которые удовлетворяли определенным критериям в глубоких ассоциациях -> это был исходный вопрос или даже на 2-м или 3-м уровне. Написание пользовательских контроллеров - единственный способ на данный момент или пересмотр клиента с большей логикой для обработки такого «обратного» поиска, вот как это делается на данный момент.

Сначала я нахожу связанную модель, которая удовлетворяет необходимым критериям, а затем из этого набора я вынимаю «отличные» доминирующие идентификаторы записи. Обычно это означает по меньшей мере одно или два запроса на сервер/уровень, потому что в последнем запросе имеется массив «ИЛИ» доминирующих идентификаторов модели.

Кроме создания запросов POST к некоторым URL на самом деле получить данные не такая большая идея, потому что она разрушает основу принципов REST: https://spring.io/understanding/REST

Смежные вопросы