【问题标题】:sails.js Blueprint query by relationsSails.js 蓝图按关系查询
【发布时间】:2015-02-01 05:56:17
【问题描述】:

我正在运行带有 postgresql 支持的sails 0.10.5,我想问一下是否有任何方法可以进行查询以按关系过滤结果。例如:

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

或者

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

或者

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

模型 Document 与 User 有一个 belongsTo 关系,该关系有一个名为 role 的属性(字符串 f.e.)。

我无法进行这样的查询,我错过了什么吗?

谢谢!

【问题讨论】:

    标签: node.js postgresql sails.js blueprint


    【解决方案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);
    },
    

    耶!现在您的 API 可以处理额外的关联过滤器,如下所示:

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

    我希望它会有所帮助。顺便说一句,我明天会找时间向 SailsJS 核心发送这个改进的拉取请求。

    P/S:SailsJS 核心制作精良。可能核心提交者太忙了,无法处理所有功能请求。让我们做出贡献!

    【讨论】:

    • 嗨 Ducky,感谢您的回答,但我无法正常工作。当我按照您的建议执行时,我总是收到“详细信息:错误:列 document.populate_user 不存在”。此外,我正在考虑一个更通用的解决方案。您可以使用点符号在关系树中导航的一种。我不知道我是否解释得很好。 =/
    • 您能否详细说明您提出请求的方式?到目前为止,这个解决方案对我来说效果很好。顺便说一句,如果 GET 不起作用,请尝试 POST(以防万一)
    • 它必须是一个 GET 请求。我的要求:http://api/documents?populate_user={where:{role:'Admin'}}
    • 我认为即使是默认的 SailsJS 蓝图也不支持像您一样调用复杂的 GET 请求 :-(
    • 必须有一个简单的方法来做到这一点!此功能在您希望按关系值排序/过滤的过滤表中非常常见。
    【解决方案2】:

    似乎“人口”在sails v0.12 中运行良好。我测试了它的第一级 - 关联并且工作正常。但是仍然没有找到一种可用且可靠的方法来仅获取满足深度关联中某些标准的主导模型记录->这是原始问题,甚至是在第 2 或第 3 级深度。编写自定义控制器是目前唯一的方法,或者用更多逻辑来检修客户端来处理这种“反向”搜索,这就是我现在的做法。

    首先我找到满足所需标准的关联模型,然后从这个集合中取出“不同”的主要记录 id。它通常意味着对服务器/级别至少有一个或两个请求,因为最终查询具有主导模型 ID 的“OR”数组。

    此外,向某个 url 发出 POST 请求以实际获取数据并不是一个好主意,因为它违反了 REST 原则的核心:https://spring.io/understanding/REST

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-30
      • 2015-02-14
      • 1970-01-01
      • 2014-05-21
      • 1970-01-01
      相关资源
      最近更新 更多