如何组成复杂的ReQL查询?

时间:2017-06-11 19:59:09

标签: rethinkdb rethinkdb-javascript reql

是否有任何最佳实践或ReQL功能有助于编写复杂的ReQL查询?

为了说明这一点,想象一下fruits表。每个文档都有以下结构。

{
    "id": 123,
    "name": "name",
    "colour": "colour",
    "weight": 5
}

如果我们想要检索所有绿色水果,我们可能会使用以下查询。

r
    .db('db')
    .table('fruits')
    .filter({colour: 'green'})

但是,在更复杂的情况下,我们可能希望使用各种复杂的命令组合。在这种情况下,可以针对每个案例编写定制查询,但这可能难以维护并且可能违反不要重复自己(DRY)原则。相反,我们可能希望编写可以链接自定义命令的定制查询,从而允许以模块化方式组合复杂查询。这可能采取以下形式。

r
    .db('db')
    .table('fruits')
    .custom(component)

component可以是一个函数,它接受命令链中的最后一个实体作为其参数并返回一些内容,如下所示。

function component(chain)
{
    return chain
        .filter({colour: 'green'});
};

这不是一个功能提案,而是一个复杂查询问题的例证,尽管这样的功能看似直观有用。

就个人而言,我自己解决这个问题的努力涉及创建compose效用函数。它以一系列函数作为主要参数。调用每个函数,传递查询链的一部分,并期望返回查询链的修订版本。迭代完成后,将返回composition个查询组件。这可以在下面看到。

function compose(queries, parameters)
{
    if (queries.length > 1)
    {
        let composition = queries[0](parameters);
        for (let index = 1; index < queries.length; index++)
        {
            let query = queries[index];
            composition = query(composition, parameters);
        };
        return composition;
    }
    else
    {
        throw 'Must be two or more queries.';
    };
};

function startQuery()
{
    return RethinkDB;
};

function filterQuery1(query)
{
    return query.filter({name: 'Grape'});
};

function filterQuery2(query)
{
    return query.filter({colour: 'Green'});
};

function filterQuery3(query)
{
    return query.orderBy(RethinkDB.desc('created'));
};

let composition = compose([startQuery, filterQuery1, filterQuery2, filterQuery3]);
composition.run(connection);

很高兴知道这样的事情是否存在,是否有处理此类案例的最佳实践,或者这是否是ReQL可以从改进中受益的领域。

1 个答案:

答案 0 :(得分:0)

在RethinkDB文档中,他们清楚地说明了这一点:所有ReQL查询都是可链接的

  

通过在编程中进行函数调用来构造查询   你已经知道的语言。您不必连接字符串或   构造专门的JSON对象来查询数据库。 所有ReQL   查询是可链接的。您从表开始并逐步链接   变换器使用的查询结束。操作

你不必撰写另一个只隐含你的代码的东西,这会使它更难以阅读并最终变得不必要。

简单的方法是将rethinkdb查询和过滤器分配到变量中,只要您需要添加更复杂的逻辑,直接添加到这些变量,然后在查询完成时运行()它

假设我必须搜索具有不同过滤器输入并获得分页的产品列表。以下代码在javascript中公开(这是仅用于说明的简单代码)

&#13;
&#13;
let sorterDirection = 'asc';
let sorterColumnName = 'created_date';

var buildFilter = r.row('app_id').eq(appId).and(r.row('status').eq('public'))

// if there is no condition to start up, you could use r.expr(true)

// append every filter into the buildFilter var if they are positive

if (escapedKeyword != "") {
buildFilter = buildFilter.and(r.row('name').default('').downcase().match(escapedKeyword))
        }

// you may have different filter to add, do the same to append them into buildFilter.

// start to make query

let query = r.table('yourTableName').filter(buildFilter);

query.orderBy(r[sorterDirection](sorterColumnName))
            .slice(pageIndex * pageSize, (pageIndex * pageSize) + pageSize).run();
&#13;
&#13;
&#13;