我想查询类似的帖子,但不想查询包含的帖子本身。
这是我的尝试:
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
}
但我尝试查询所有具有类似keywords
和title
的帖子,其中包括来自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。