Fix - Update searchVector when labelIdentifier is updated (#16940)
Fixes https://github.com/twentyhq/twenty/issues/16891 In next PR, validation rules will be added in migration logic
This commit is contained in:
+2
@@ -84,6 +84,7 @@ export const fromUpdateObjectInputToFlatObjectMetadataAndRelatedFlatEntities =
|
||||
flatViewFieldsToCreate,
|
||||
flatViewFieldsToUpdate,
|
||||
otherObjectFlatFieldMetadatasToUpdate,
|
||||
sameObjectFlatFieldMetadatasToUpdate,
|
||||
} = handleFlatObjectMetadataUpdateSideEffect({
|
||||
fromFlatObjectMetadata: existingFlatObjectMetadata,
|
||||
toFlatObjectMetadata,
|
||||
@@ -100,5 +101,6 @@ export const fromUpdateObjectInputToFlatObjectMetadataAndRelatedFlatEntities =
|
||||
flatViewFieldsToCreate,
|
||||
flatViewFieldsToUpdate,
|
||||
otherObjectFlatFieldMetadatasToUpdate,
|
||||
sameObjectFlatFieldMetadatasToUpdate,
|
||||
};
|
||||
};
|
||||
|
||||
+24
@@ -6,12 +6,14 @@ import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-m
|
||||
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { recomputeIndexAfterFlatObjectMetadataSingularNameUpdate } from 'src/engine/metadata-modules/flat-object-metadata/utils/recompute-index-after-flat-object-metadata-singular-name-update.util';
|
||||
import { recomputeSearchVectorFieldAfterLabelIdentifierUpdate } from 'src/engine/metadata-modules/flat-object-metadata/utils/recompute-search-vector-field-after-label-identifier-update.util';
|
||||
import { recomputeViewFieldIdentifierAfterFlatObjectIdentifierUpdate } from 'src/engine/metadata-modules/flat-object-metadata/utils/recompute-view-field-identifier-after-flat-object-identifier-update.util';
|
||||
import { renameRelatedMorphFieldOnObjectNamesUpdate } from 'src/engine/metadata-modules/flat-object-metadata/utils/rename-related-morph-field-on-object-names-update.util';
|
||||
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
|
||||
|
||||
export type FlatObjectMetadataUpdateSideEffects = {
|
||||
otherObjectFlatFieldMetadatasToUpdate: FlatFieldMetadata[];
|
||||
sameObjectFlatFieldMetadatasToUpdate: FlatFieldMetadata[];
|
||||
flatViewFieldsToUpdate: FlatViewField[];
|
||||
flatViewFieldsToCreate: FlatViewField[];
|
||||
flatIndexMetadatasToUpdate: FlatIndexMetadata[];
|
||||
@@ -81,6 +83,27 @@ export const handleFlatObjectMetadataUpdateSideEffect = ({
|
||||
flatViewFieldsToUpdate: [],
|
||||
};
|
||||
|
||||
const sameObjectFlatFieldMetadatasToUpdate: FlatFieldMetadata[] = [];
|
||||
|
||||
if (
|
||||
toFlatObjectMetadata.isSearchable &&
|
||||
isDefined(toFlatObjectMetadata.labelIdentifierFieldMetadataId) &&
|
||||
fromFlatObjectMetadata.labelIdentifierFieldMetadataId !==
|
||||
toFlatObjectMetadata.labelIdentifierFieldMetadataId
|
||||
) {
|
||||
const updatedSearchVectorField =
|
||||
recomputeSearchVectorFieldAfterLabelIdentifierUpdate({
|
||||
existingFlatObjectMetadata: fromFlatObjectMetadata,
|
||||
flatFieldMetadataMaps,
|
||||
updatedLabelIdentifierFieldMetadataId:
|
||||
toFlatObjectMetadata.labelIdentifierFieldMetadataId,
|
||||
});
|
||||
|
||||
if (isDefined(updatedSearchVectorField)) {
|
||||
sameObjectFlatFieldMetadatasToUpdate.push(updatedSearchVectorField);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
flatIndexMetadatasToUpdate: [
|
||||
...morphRelatedFlatIndexesToUpdate,
|
||||
@@ -89,5 +112,6 @@ export const handleFlatObjectMetadataUpdateSideEffect = ({
|
||||
flatViewFieldsToCreate,
|
||||
flatViewFieldsToUpdate,
|
||||
otherObjectFlatFieldMetadatasToUpdate: morphFlatFieldMetadatasToUpdate,
|
||||
sameObjectFlatFieldMetadatasToUpdate,
|
||||
};
|
||||
};
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
import { type FieldMetadataType } from 'twenty-shared/types';
|
||||
import { findOrThrow, isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import {
|
||||
ObjectMetadataException,
|
||||
ObjectMetadataExceptionCode,
|
||||
} from 'src/engine/metadata-modules/object-metadata/object-metadata.exception';
|
||||
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/get-ts-vector-column-expression.util';
|
||||
import { type SearchableFieldType } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/is-searchable-field.util';
|
||||
|
||||
type RecomputeSearchVectorFieldAfterLabelIdentifierUpdateArgs = {
|
||||
existingFlatObjectMetadata: FlatObjectMetadata;
|
||||
updatedLabelIdentifierFieldMetadataId: string;
|
||||
} & Pick<AllFlatEntityMaps, 'flatFieldMetadataMaps'>;
|
||||
|
||||
export const recomputeSearchVectorFieldAfterLabelIdentifierUpdate = ({
|
||||
existingFlatObjectMetadata,
|
||||
flatFieldMetadataMaps,
|
||||
updatedLabelIdentifierFieldMetadataId,
|
||||
}: RecomputeSearchVectorFieldAfterLabelIdentifierUpdateArgs):
|
||||
| FlatFieldMetadata<FieldMetadataType.TS_VECTOR>
|
||||
| undefined => {
|
||||
const objectFlatFieldMetadatas =
|
||||
findManyFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
flatEntityIds: existingFlatObjectMetadata.fieldMetadataIds,
|
||||
});
|
||||
|
||||
const searchVectorField = findOrThrow(
|
||||
objectFlatFieldMetadatas,
|
||||
(field) => field.name === SEARCH_VECTOR_FIELD.name,
|
||||
) as FlatFieldMetadata<FieldMetadataType.TS_VECTOR>;
|
||||
|
||||
const newLabelIdentifierField = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
flatEntityId: updatedLabelIdentifierFieldMetadataId,
|
||||
});
|
||||
|
||||
if (!isDefined(newLabelIdentifierField)) {
|
||||
throw new ObjectMetadataException(
|
||||
`New label identifier field not found for object metadata`,
|
||||
ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const newAsExpression = getTsVectorColumnExpressionFromFields([
|
||||
{
|
||||
name: newLabelIdentifierField.name,
|
||||
type: newLabelIdentifierField.type as SearchableFieldType,
|
||||
},
|
||||
]);
|
||||
|
||||
return {
|
||||
...searchVectorField,
|
||||
settings: {
|
||||
...searchVectorField.settings,
|
||||
asExpression: newAsExpression,
|
||||
generatedType: 'STORED',
|
||||
},
|
||||
};
|
||||
} catch {
|
||||
throw new ObjectMetadataException(
|
||||
`Failed to compute search vector column expression for field ${newLabelIdentifierField.name}`,
|
||||
ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT,
|
||||
);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user