按急切结果计数排序记录并根据 Objection.js 中的结果实现分页?

Order records by eager results count and implement pagination based on that in Objection.js?

我有这些表:

  1. Users
  2. Skills
  3. Has_skills (user_id, skill_id)

我将一组技能 ID 传递给函数,该函数应该获取至少具有其中一项技能的用户。该查询在某种程度上应该是高效的,因此它可以获取多个用户(限制、范围或换句话说分页功能),但不是从 ID 为 0 的用户开始然后向上的范围,而是从用户开始的范围最匹配的技能到最少。

那么查询如何根据匹配技能的数量从最匹配技能到最少匹配技能对记录进行排序,以便我可以根据这些结果添加分页?我假设我应该另外调整 has_skills 上的 modifyEager 并对其进行计数,然后实现分页范围,但我不完全确定该怎么做。所以最终,这是我需要添加的:

  1. 查询应首先根据匹配技能的数量对记录进行排序/排序
  2. 为了分页和更好的性能,以上条件应该受用户数或范围限制

这是我的功能:

async function getUsersWithPassedSkillIds({ skillIds }) {
    const users = await User.query()
        .select('users.id', 'users.name')
        .joinEager('has_skills')
        .modifyEager('has_skills', builder => builder.select('id', 'name'))
        .whereIn('has_skills.id', skillIds)

    return users
}

Objection.js 的作者帮助我完成了这项工作!

// Fetch the users who have at least one matching skill
const hasSkillsSubquery = User.relatedQuery("skills").whereIn(
  "has_skills.skill_id",
  skillIds
);

const users = await User.query()
  .select("users.id", "users.name")
  // Use .eager instead of .joinEager as pagination doesn't work with it due to joins.
  .eager("skills")
  // Optional: Populating the matched skills
  .modifyEager("skills", builder =>
    builder.select("skills.id", "skills.name").whereIn("skills.id", skillIds)
  )
  // Only taking into account users who have at least 1 matched skill
  .whereExists(hasSkillsSubquery.clone())
  // Sorting users by matched skills
  .orderByRaw("(?) DESC", hasSkillsSubquery.clone().count())
  // This would return the user with the most matched skills.
  // If you want to fetch 10 users ordered by number of matching skills: .range(0, 9)
  .range(0, 0);