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



我想查询类似的帖子,但不想查询包含的帖子本身。

这是我的尝试:

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的帖子,其中包括来自whereNot的帖子。我以后得把它过滤掉。

如何在不包括帖子本身的情况下查询帖子的相似性?

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

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

请注意,这些子句没有特定的分组。所有这些都适用,并且因为有些是OR,所以不要求slug子句的求值结果为true。

一种解决方法是使用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仅适用于组内,因此组外的所有子句的求值结果必须仍然为true。