数据库的一部分:
故事实体:
@Entity('stories')
export class StoryEntity {
@PrimaryGeneratedColumn()
id: number
@Column()
slug: string
@Column()
title: string
@Column()
description: string
@Column({default: 0})
words: number
@Column({default: 0})
pages: number
@ManyToOne(() => RatingEntity, (rating) => rating.stories, {eager: true})
rating: RatingEntity
@ManyToOne(() => FocusEntity, (focus) => focus.stories, {eager: true})
focus: FocusEntity
@Column({
type: 'enum',
enum: StoryStatuses,
default: StoryStatuses.IN_PROGRESS,
})
status: StoryStatuses
@Column({default: 0})
favoriteCount: number
@Column({default: 0})
followCount: number
@Column({default: 0})
viewCount: number
@Column({default: false})
isPublished: boolean
@ManyToOne(() => UserEntity, (user) => user.stories, {eager: true})
author: UserEntity
@OneToMany(() => ChapterEntity, (chapter) => chapter.story, {
onDelete: 'CASCADE',
eager: true,
})
chapters: ChapterEntity[]
@ManyToMany(() => FandomEntity)
@JoinTable()
fandoms: FandomEntity[]
@Column('text', {array: true})
characters: string[]
@Column('text', {array: true})
pairings: string[]
@ManyToMany(() => TagEntity, {eager: true})
@JoinTable()
tags: TagEntity[]
@ManyToMany(() => UserEntity)
@JoinTable()
betas: UserEntity[]
@Column({type: 'timestamp', default: () => 'CURRENT_TIMESTAMP'})
createdAt: Date
@Column({type: 'timestamp', default: () => 'CURRENT_TIMESTAMP'})
updatedAt: Date
@BeforeUpdate()
updateTimestamp() {
this.updatedAt = new Date()
}
@BeforeInsert()
@BeforeUpdate()
slugifyTitle() {
this.slug = slugify(this.title)
}
countWords(): number {
if (this.chapters) {
this.words = this.chapters.reduce((acc, prev: ChapterEntity) => {
return (acc += prev.words)
}, 0)
}
return this.words
}
countViews() {
this.chapters.forEach((chapter) => (this.viewCount += chapter.viewCount))
}
}
标记实体:
@Entity('tags')
export class TagEntity {
@PrimaryGeneratedColumn()
id: number
@Column()
title: string
@Column({default: ''})
description: string
@BeforeInsert()
@BeforeUpdate()
normalizeTitle() {
this.title = this.title.trim()
}
}
还有这样的代码:
const queryBuilder = this.storyRepository
.createQueryBuilder('story')
.leftJoinAndSelect('story.tags', 'tags')
.leftJoinAndSelect('story.fandoms', 'fandoms')
.leftJoinAndSelect('story.author', 'author')
.leftJoinAndSelect('story.rating', 'rating')
.leftJoinAndSelect('story.focus', 'focus')
if (filterQuery.tags) {
const tags = filterQuery.tags.split(';')
queryBuilder.andWhere('tags.title IN (:...tags)', {
tags,
})
}
if (filterQuery.excludeTags) {
const tags = filterQuery.excludeTags.split(';')
queryBuilder.andWhere('tags.title NOT IN (:...tags)', {
tags
})
}
const storyCount = await queryBuilder.getCount()
const stories = await queryBuilder.getMany()
return {
stories: await Promise.all(
stories.map(async (story) => {
delete story.chapters
return (await this.buildResponse(story, currentUserId)).story
})
),
storyCount,
}
如果我返回一个响应而不应用过滤器,我会得到预期的结果-数据库中的所有实体:without filter response
...
"tags": [
{
"id": 2,
"title": "AU",
"description": "test-description"
},
{
"id": 1,
"title": "Action",
"description": "test-description"
}
],
...
正如您所注意到的,在标记数组中有两个标记,标签分别为“Au”和“Action”,但是只要我在响应中应用过滤器,就只返回过滤器中指定的标记:filter response
// filter value "AU"
...
"tags": [
{
"id": 2,
"title": "AU",
"description": "test-description"
}
],
...
有什么问题吗?我真的不明白
1条答案
按热度按时间jchrr9hc1#
作为一种方法,你可以用不同的别名加入它两次,然后过滤掉其中一个。这是一个有点黑客,但得到的工作完成。