From 0b9df572ba042c57cc1f0bc9ca42d03121254410 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 4 Aug 2026 19:52:15 +0200 Subject: [PATCH] Task/optimize performance of search in assistant (#7534) * Improve performance of search in assistant by reusing cached portfolio snapshot * Update changelog --- CHANGELOG.md | 10 +++++++ .../src/app/portfolio/portfolio.service.ts | 30 ++++++++++++------- .../portfolio-position.interface.ts | 1 + 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c90fdf30..7bd3340ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Changed + +- Optimized the performance of the search in the assistant by reusing the cached portfolio snapshot + +### Fixed + +- Fixed the fuzzy search for the holdings in the assistant + ## 3.41.0 - 2026-08-03 ### Added diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 0a69cf32d..70106bdc1 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -165,6 +165,10 @@ export class PortfolioService { }; } + const filtersWithoutSearchQueryFilter = filters?.filter(({ type }) => { + return type !== 'SEARCH_QUERY'; + }); + const [accounts, details, user] = await Promise.all([ this.accountService.accounts({ where, @@ -176,8 +180,8 @@ export class PortfolioService { orderBy: { name: 'asc' } }), this.getDetails({ - filters, withExcludedAccounts, + filters: filtersWithoutSearchQueryFilter, impersonationId: userId, userId: this.request.user.id }), @@ -369,14 +373,6 @@ export class PortfolioService { userId: string; }) { userId = await this.getUserId(impersonationId, userId); - const { holdings: holdingsMap } = await this.getDetails({ - dateRange, - filters, - impersonationId, - userId - }); - - let holdings = Object.values(holdingsMap); const { SEARCH_QUERY: [filterBySearchQuery] = [] } = groupBy( filters, @@ -385,9 +381,22 @@ export class PortfolioService { } ); + const filtersWithoutSearchQueryFilter = filters?.filter(({ type }) => { + return type !== 'SEARCH_QUERY'; + }); + + const { holdings: holdingsMap } = await this.getDetails({ + dateRange, + impersonationId, + userId, + filters: filtersWithoutSearchQueryFilter + }); + + let holdings = Object.values(holdingsMap); + if (filterBySearchQuery) { const fuse = new Fuse(holdings, { - keys: ['isin', 'name', 'symbol'], + keys: ['assetProfile.isin', 'assetProfile.name', 'assetProfile.symbol'], threshold: 0.3 }); @@ -651,6 +660,7 @@ export class PortfolioService { }; } ), + isin: assetProfile.isin, name: assetProfile.name, sectors: assetProfile.sectors, symbol: assetProfile.symbol, diff --git a/libs/common/src/lib/interfaces/portfolio-position.interface.ts b/libs/common/src/lib/interfaces/portfolio-position.interface.ts index cf71b20ca..388e661f7 100644 --- a/libs/common/src/lib/interfaces/portfolio-position.interface.ts +++ b/libs/common/src/lib/interfaces/portfolio-position.interface.ts @@ -15,6 +15,7 @@ export interface PortfolioPosition { | 'currency' | 'dataSource' | 'holdings' + | 'isin' | 'name' | 'sectors' | 'symbol'