compute all facets in one go
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
@@ -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 };
|
||||
|
||||
Reference in New Issue
Block a user