Merge pull request #29368 from tylerd-canva/catalog-backend-sortField-distinct
Fix for duplicate results in queryEntities when using an orderField
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Fix for duplicate results in `queryEntities` when providing an `orderField` parameter
|
||||
@@ -1970,6 +1970,87 @@ describe('DefaultEntitiesCatalog', () => {
|
||||
).resolves.toEqual(['BB']);
|
||||
},
|
||||
);
|
||||
|
||||
it.each(databases.eachSupportedId())(
|
||||
'should not return duplicate entities when using orderField, %p',
|
||||
async databaseId => {
|
||||
await createDatabase(databaseId);
|
||||
|
||||
// Create a few test entities with different names to sort by
|
||||
const entities = [
|
||||
{
|
||||
apiVersion: 'a',
|
||||
kind: 'k',
|
||||
metadata: {
|
||||
name: 'a-entity',
|
||||
title: 'A Test Entity',
|
||||
uid: 'uid-a',
|
||||
},
|
||||
spec: {},
|
||||
},
|
||||
{
|
||||
apiVersion: 'a',
|
||||
kind: 'k',
|
||||
metadata: {
|
||||
name: 'b-entity',
|
||||
title: 'B Test Entity',
|
||||
uid: 'uid-b',
|
||||
},
|
||||
spec: {},
|
||||
},
|
||||
{
|
||||
apiVersion: 'a',
|
||||
kind: 'k',
|
||||
metadata: {
|
||||
name: 'c-entity',
|
||||
title: 'C Test Entity',
|
||||
uid: 'uid-c',
|
||||
},
|
||||
spec: {},
|
||||
},
|
||||
];
|
||||
|
||||
await Promise.all(entities.map(e => addEntityToSearch(e)));
|
||||
|
||||
// Manually insert duplicate search entries for the same entities
|
||||
// I'm not sure exactly how this happens but I have seen it in the real world
|
||||
await knex<DbSearchRow>('search').insert([
|
||||
{
|
||||
entity_id: 'uid-a',
|
||||
key: 'metadata.title',
|
||||
value: 'a test entity',
|
||||
original_value: 'A Test Entity',
|
||||
},
|
||||
{
|
||||
entity_id: 'uid-b',
|
||||
key: 'metadata.title',
|
||||
value: 'b test entity',
|
||||
original_value: 'B Test Entity',
|
||||
},
|
||||
]);
|
||||
|
||||
const catalog = new DefaultEntitiesCatalog({
|
||||
database: knex,
|
||||
logger: mockServices.logger.mock(),
|
||||
stitcher,
|
||||
});
|
||||
|
||||
// Query with orderField
|
||||
const response = await catalog.queryEntities({
|
||||
orderFields: [{ field: 'metadata.title', order: 'asc' }],
|
||||
credentials: mockCredentials.none(),
|
||||
});
|
||||
|
||||
const resultEntities = entitiesResponseToObjects(response.items);
|
||||
|
||||
// Ensure we get exactly 3 entities back, sorted, with no duplicates
|
||||
expect(resultEntities.map(e => e!.metadata.name)).toEqual([
|
||||
'a-entity',
|
||||
'b-entity',
|
||||
'c-entity',
|
||||
]);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('removeEntityByUid', () => {
|
||||
|
||||
@@ -285,6 +285,7 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog {
|
||||
|
||||
if (sortField) {
|
||||
inner
|
||||
.distinct()
|
||||
.leftOuterJoin('search', qb =>
|
||||
qb
|
||||
.on('search.entity_id', 'final_entities.entity_id')
|
||||
|
||||
Reference in New Issue
Block a user