如何用 Knex.js 查询 similars 而不是 self?

How to query similars but not self with Knex.js?

我想查询类似的 post 但不包括 post 本身。

这是我的尝试:

export async function getSimilars(slug: string) {
  const excludeThis = await getBySlug(slug)

  const posts = await knex('posts')
    .whereNot({ slug }) // Each post has its own unique slug, used nanoid(11).
    .andWhere({ is_active: true })
    .andWhere({ type: excludeThis.type })
    .orWhere('keywords', 'ilike', `%${excludeThis.keywords}%`)
    .orWhere('title', 'ilike', `%${excludeThis.title}%`)
    .limit(10)
    .orderBy(orderBy)

  // Since posts includes excludeThis post, I have to filter it out here.
  const result = posts.filter(p => p.slug !== slug)
  return result
}

但我尝试查询所有具有相似 keywordstitle 的 post,其中包括来自 whereNot 的 post。以后得过滤掉了。

如何在不包含 post 本身的情况下查询 post 的相似项?

我怀疑您对 orWhere 的使用否定了您对 whereNot 的使用。如果不对其进行测试,我希望它生成 SQL 有点像以下内容:

SELECT * FROM posts
  WHERE slug != 'whatever'
    AND ...
    AND ...
    OR ...
    OR ...

请注意,这些条款没有特定的分组。所有这些都适用,并且因为有些是 OR,所以不要求您的 slug 子句计算为真。

解决此问题的一种方法是使用 Knex 解决方案进行分组:传递函数而不是对象。

const posts = await knex('posts')
  .where({
    is_active: true,
    type: excludeThis.type
  })
  .andWhere(qb =>
    qb
      .where('keywords', 'ilike', `%${excludeThis.keywords}%`)
      .orWhere('title', 'ilike', `%${excludeThis.title}%`)
  )
  .andWhereNot({ slug })

这将按照以下行生成 SQL:

SELECT * FROM posts
  WHERE ...
    AND ...
    AND ( ... OR ... )
    AND slug != 'whatever'

这里的OR只适用于组内,所以组外的所有子句仍必须为真。