0

是否有任何有助于编写复杂 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 可以从改进中受益的领域。

4

1 回答 1

0

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

查询是通过使用您已经知道的编程语言进行函数调用来构建的。您不必连接字符串或构造专门的 JSON 对象来查询数据库。所有 ReQL 查询都是可链接的。您从一个表开始,并使用 . 操作员

您不必编写仅隐含代码的其他内容,这会使阅读变得更加困难并且最终变得不必要。

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

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

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();

于 2017-06-13T15:58:43.340 回答