From 271af373272263ec9f54b7f24ac82463e756509e Mon Sep 17 00:00:00 2001 From: Marie <51697796+ijreilly@users.noreply.github.com> Date: Tue, 19 Nov 2024 19:07:57 +0100 Subject: [PATCH] Fix relations in search queries (#8595) We were not handling relations in the search resolver, which started being an issue as we query those relations in the combinedSearch queries (introduced here https://github.com/twentyhq/twenty/pull/8564); they were nullified in the response payload. The response was overwriting findManyRecords results in the cache as it contained the exact same fields. So we now 1. Handle relations in the search resolver 2. Stop querying relations in search queries (no use) --- .../useGenerateCombinedSearchRecordsQuery.ts | 8 +----- .../graphql-query-search-resolver.service.ts | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/multiple-objects/hooks/useGenerateCombinedSearchRecordsQuery.ts b/packages/twenty-front/src/modules/object-record/multiple-objects/hooks/useGenerateCombinedSearchRecordsQuery.ts index fc7725c3a..6f3fa418a 100644 --- a/packages/twenty-front/src/modules/object-record/multiple-objects/hooks/useGenerateCombinedSearchRecordsQuery.ts +++ b/packages/twenty-front/src/modules/object-record/multiple-objects/hooks/useGenerateCombinedSearchRecordsQuery.ts @@ -5,7 +5,6 @@ import { useRecoilValue } from 'recoil'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery'; import { RecordGqlOperationSignature } from '@/object-record/graphql/types/RecordGqlOperationSignature'; -import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields'; import { getSearchRecordsQueryResponseField } from '@/object-record/utils/getSearchRecordsQueryResponseField'; import { isObjectMetadataItemSearchable } from '@/object-record/utils/isObjectMetadataItemSearchable'; import { isNonEmptyArray } from '~/utils/isNonEmptyArray'; @@ -68,7 +67,7 @@ export const useGenerateCombinedSearchRecordsQuery = ({ ) { ${filteredQueryKeyWithObjectMetadataItemArray .map( - ({ objectMetadataItem, fields }) => + ({ objectMetadataItem }) => `${getSearchRecordsQueryResponseField(objectMetadataItem.namePlural)}(filter: $filter${capitalize( objectMetadataItem.nameSingular, )}, @@ -79,11 +78,6 @@ export const useGenerateCombinedSearchRecordsQuery = ({ node ${mapObjectMetadataToGraphQLQuery({ objectMetadataItems: objectMetadataItems, objectMetadataItem, - recordGqlFields: - fields ?? - generateDepthOneRecordGqlFields({ - objectMetadataItem, - }), })} cursor } diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-search-resolver.service.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-search-resolver.service.ts index c9e7455a3..84f6c3ad7 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-search-resolver.service.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-search-resolver.service.ts @@ -14,8 +14,10 @@ import { WorkspaceQueryRunnerOptions } from 'src/engine/api/graphql/workspace-qu import { SearchResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/constants/query-max-records.constant'; +import { GraphqlQuerySelectedFieldsResult } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-selected-fields/graphql-selected-fields.parser'; import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser'; import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper'; +import { ProcessNestedRelationsHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/process-nested-relations.helper'; import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/constants/search-vector-field.constants'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { isDefined } from 'src/utils/is-defined'; @@ -114,11 +116,37 @@ export class GraphqlQuerySearchResolverService const selectedFields = graphqlFields(info); + const graphqlQuerySelectedFieldsResult: GraphqlQuerySelectedFieldsResult = + graphqlQueryParser.parseSelectedFields( + objectMetadataItemWithFieldMaps, + selectedFields, + ); + const totalCount = isDefined(selectedFields.totalCount) ? await queryBuilderWithFilter.getCount() : 0; const order = undefined; + const processNestedRelationsHelper = new ProcessNestedRelationsHelper(); + + const dataSource = + await this.twentyORMGlobalManager.getDataSourceForWorkspace( + authContext.workspace.id, + ); + + if (graphqlQuerySelectedFieldsResult.relations) { + await processNestedRelationsHelper.processNestedRelations({ + objectMetadataMaps, + parentObjectMetadataItem: objectMetadataItemWithFieldMaps, + parentObjectRecords: objectRecords, + relations: graphqlQuerySelectedFieldsResult.relations, + aggregate: graphqlQuerySelectedFieldsResult.aggregate, + limit, + authContext, + dataSource, + }); + } + return typeORMObjectRecordsParser.createConnection({ objectRecords: objectRecords ?? [], objectName: objectMetadataItemWithFieldMaps.nameSingular,