使用 knex 将连接限制为一行

yar*_*ism 1 greatest-n-per-group knex.js

我正在尝试使用连接从两个表中获取数据。问题是 forum_posts 将包含多个具有相同 thread_id 的项目。我只想通过 id 或通过创建日期来获得第一个。

function getByGroup(groupId) {
    return knex('forum_threads')
        .select('forum_threads.id', 'forum_threads.updated_at', 'forum_posts.content')
        .where('forum_threads.group_id', '=', groupId)
        .leftJoin('forum_posts', function() {
            this.on('forum_posts.thread_id', '=', 'forum_threads.id');
        })
        .orderBy('updated_at', 'desc')
        .then(function(threads) {
            return threads;
        });
}
Run Code Online (Sandbox Code Playgroud)

我想在连接中添加一个限制(1)或一个分钟,但不完全确定如何去做。

Gar*_*ryL 5

您需要在左联接条件中添加如下所示的过滤器:

.andOn('forum_posts.created_at', '=', knex.raw("(select min(created_at) from forum_posts where forum_posts.thread_id = forum_threads.id)"))
Run Code Online (Sandbox Code Playgroud)

这是说,包括论坛发帖记录(左连接匹配),如果它具有最小updated_at的那个值id

完整的代码。下面的代码没有经过测试,虽然我确实在我的一段代码中测试了上面的代码片段。

function getByGroup(groupId) {
  return knex('forum_threads')
    .select('forum_threads.id', 'forum_threads.updated_at', 'forum_posts.content')
    .where('forum_threads.group_id', '=', groupId)
    .leftJoin('forum_posts', function() {
        this.on('forum_posts.thread_id', '=', 'forum_threads.id')
            /* The new line here */
            .andOn('forum_posts.created_at', '=', knex.raw("(select min(created_at) from forum_posts where forum_posts.thread_id = forum_threads.id)"))
    })
    .orderBy('updated_at', 'desc')
    .then(function(threads) {
        return threads;
    });
}
Run Code Online (Sandbox Code Playgroud)

干杯!

PS:你没有问,但我在调试 Knex 时发现非常有帮助的是.on()查询报告子句:

    // ...
    .orderBy('updated_at', 'desc')
    /* your code above */
    .on('query', function(data) {
        // outputs the SQL query you generated & runtime data bindings.
        console.log(data);
    })
    .on('query-error', function(error, obj) {
        // outputs the Knex failed query, data, etc.
        console.log("Error:", error);
        console.log("Object: ", obj);
    })
    /* your code below */
    .then(function(threads) {
        return threads;
    });
Run Code Online (Sandbox Code Playgroud)