compute all facets in one go

Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
Fredrik Adelöw
2024-11-26 13:31:04 +01:00
parent 1ac6c623d0
commit 1d0bc117d5
3 changed files with 81 additions and 18 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend': minor
---
Fetch all facets in a single database query
@@ -2060,6 +2060,50 @@ describe('DefaultEntitiesCatalog', () => {
});
},
);
it.each(databases.eachSupportedId())(
'works with a mixture of present and missing facets, %p',
async databaseId => {
await createDatabase(databaseId);
await addEntityToSearch({
apiVersion: 'a',
kind: 'k',
metadata: {
name: 'one',
},
spec: {},
});
await addEntityToSearch({
apiVersion: 'a',
kind: 'k',
metadata: {
name: 'two',
},
spec: {},
});
const catalog = new DefaultEntitiesCatalog({
database: knex,
logger: mockServices.logger.mock(),
stitcher,
});
await expect(
catalog.facets({
facets: ['metadata.name', 'missing'],
credentials: mockCredentials.none(),
}),
).resolves.toEqual({
facets: {
'metadata.name': expect.arrayContaining([
{ value: 'one', count: 1 },
{ value: 'two', count: 1 },
]),
missing: [],
},
});
},
);
});
});
@@ -720,26 +720,40 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog {
}
async facets(request: EntityFacetsRequest): Promise<EntityFacetsResponse> {
const query = this.database<DbSearchRow>('search')
.whereIn(
'search.key',
request.facets.map(f => f.toLocaleLowerCase('en-US')),
)
.whereNotNull('search.original_value')
.select({
facet: 'search.key',
value: 'search.original_value',
count: this.database.raw('count(*)'),
})
.groupBy(['search.key', 'search.original_value']);
if (request.filter) {
parseFilter(
request.filter,
query,
this.database,
false,
'search.entity_id',
);
}
const rows = await query;
const facets: EntityFacetsResponse['facets'] = {};
const db = this.database;
for (const facet of request.facets) {
const dbQuery = db<DbSearchRow>('search')
.where('search.key', facet.toLocaleLowerCase('en-US'))
.whereNotNull('search.original_value')
.select({ value: 'search.original_value', count: db.raw('count(*)') })
.groupBy('search.original_value');
if (request?.filter) {
parseFilter(request.filter, dbQuery, db, false, 'search.entity_id');
}
const result = await dbQuery;
facets[facet] = result.map(data => ({
value: String(data.value),
count: Number(data.count),
}));
const facetLowercase = facet.toLocaleLowerCase('en-US');
facets[facet] = rows
.filter(row => row.facet === facetLowercase)
.map(row => ({
value: String(row.value),
count: Number(row.count),
}));
}
return { facets };