typescript 在typeorm中筛选数组时遇到问题,QueryBuilder只返回找到的第一个匹配项

zc0qhyus  于 2023-02-17  发布在  TypeScript
关注(0)|答案(1)|浏览(157)

数据库的一部分:
故事实体:

@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"
   }
 ],
...

有什么问题吗?我真的不明白

jchrr9hc

jchrr9hc1#

作为一种方法,你可以用不同的别名加入它两次,然后过滤掉其中一个。这是一个有点黑客,但得到的工作完成。

.leftJoinAndSelect('story.tags', 'tags')
   .leftJoin('story.tags', 'tagsForFilter')

   andWhere('tagsForFilter.title IN (:...tags)', {....

相关问题