Skip to content

Commit

Permalink
fix(core): handle $fulltext search correctly in nested queries
Browse files Browse the repository at this point in the history
Closes #3696
  • Loading branch information
B4nan committed Nov 5, 2022
1 parent ed43925 commit 9a2f535
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 3 deletions.
11 changes: 8 additions & 3 deletions packages/knex/src/query/QueryBuilderHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -486,10 +486,15 @@ export class QueryBuilderHelper {
}

if (op === '$fulltext') {
const meta = this.metadata.get(this.entityName);
const columnName = key.includes('.') ? key.split('.')[1] : key;
const [a, f] = this.splitField(key);
const prop = this.getProperty(f, a);

qb[m](this.knex.raw(this.platform.getFullTextWhereClause(meta.properties[columnName]), {
/* istanbul ignore next */
if (!prop) {
throw new Error(`Cannot use $fulltext operator on ${key}, property not found`);
}

qb[m](this.knex.raw(this.platform.getFullTextWhereClause(prop), {
column: this.mapper(key, type, undefined, null),
query: value[op],
}));
Expand Down
90 changes: 90 additions & 0 deletions tests/issues/GH3696.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { Collection, Entity, Index, ManyToMany, PrimaryKey, Property, Unique } from '@mikro-orm/core';
import { FullTextType, MikroORM } from '@mikro-orm/postgresql';

@Entity()
@Unique({ properties: ['name'] })
export class Artist {

@PrimaryKey()
id!: number;

@Property()
name: string;

@Index({ type: 'fulltext' })
@Property({ type: FullTextType, onUpdate: (artist: Artist) => artist.name })
searchableName!: string;

constructor(artist: any) {
this.id = artist.id;
this.name = artist.name;
this.searchableName = artist.name;
}

}

@Entity()
export class Song {

@PrimaryKey()
id!: number;

@Property()
title: string;

@ManyToMany(() => Artist)
artists = new Collection<Artist>(this);

@Index({ type: 'fulltext' })
@Property({ type: FullTextType, onUpdate: (song: Song) => song.title })
searchableTitle!: string;

constructor(song: any) {
this.id = song.id;
this.title = song.title;
this.searchableTitle = song.title;
}

}

let orm: MikroORM;

beforeAll(async () => {
orm = await MikroORM.init({
entities: [Song],
dbName: 'mikro_orm_test_3696',
});
await orm.schema.refreshDatabase();
});

afterAll(async () => {
await orm.close(true);
});

test('GH issue 3696', async () => {
const artist = orm.em.create(Artist, {
name: 'Taylor Swift',
searchableName: 'Taylor Swift',
});
const song = orm.em.create(Song, {
title: 'Anti-Hero',
searchableTitle: 'Anti--Hero',
});
song.artists.add(artist);
await orm.em.flush();
orm.em.clear();

const results = await orm.em.find(Song, {
searchableTitle: { $fulltext: 'anti' },
artists: { searchableName: { $fulltext: 'taylor' } },
}, { populate: ['artists'] });
expect(results).toHaveLength(1);
expect(results[0]).toMatchObject({
title: 'Anti-Hero',
searchableTitle: "'anti':1 'hero':2",
});
expect(results[0].artists[0]).toMatchObject({
name: 'Taylor Swift',
searchableName: "'swift':2 'taylor':1",
});
});

0 comments on commit 9a2f535

Please sign in to comment.