Implement search for rich text fields and use it for notes (#7953)

Co-authored-by: Weiko <corentin@twenty.com>
This commit is contained in:
Marie
2024-10-23 15:49:10 +02:00
committed by GitHub
parent 45b3992784
commit 849d7c2423
6 changed files with 89 additions and 31 deletions

View File

@ -11,6 +11,7 @@ import {
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
import {
WorkspaceMigrationColumnAction,
WorkspaceMigrationColumnActionType,
WorkspaceMigrationEntity,
WorkspaceMigrationTableAction,
@ -87,29 +88,57 @@ export class WorkspaceMigrationFieldFactory {
): Promise<Partial<WorkspaceMigrationEntity>[]> {
const workspaceMigrations: Partial<WorkspaceMigrationEntity>[] = [];
for (const fieldMetadata of fieldMetadataCollection) {
if (fieldMetadata.type === FieldMetadataType.RELATION) {
continue;
}
const fieldMetadataCollectionGroupByObjectMetadataId =
fieldMetadataCollection.reduce(
(result, currentFieldMetadata) => {
result[currentFieldMetadata.objectMetadataId] = [
...(result[currentFieldMetadata.objectMetadataId] || []),
currentFieldMetadata,
];
const migrations: WorkspaceMigrationTableAction[] = [
{
name: computeObjectTargetTable(
originalObjectMetadataMap[fieldMetadata.objectMetadataId],
),
action: WorkspaceMigrationTableActionType.ALTER,
columns: this.workspaceMigrationFactory.createColumnActions(
return result;
},
{} as Record<string, FieldMetadataEntity[]>,
);
for (const objectMetadataId in fieldMetadataCollectionGroupByObjectMetadataId) {
const fieldMetadataCollection =
fieldMetadataCollectionGroupByObjectMetadataId[objectMetadataId];
const columns: WorkspaceMigrationColumnAction[] = [];
const objectMetadata =
originalObjectMetadataMap[fieldMetadataCollection[0]?.objectMetadataId];
for (const fieldMetadata of fieldMetadataCollection) {
// Relations are handled in workspace-migration-relation.factory.ts
if (fieldMetadata.type === FieldMetadataType.RELATION) {
continue;
}
columns.push(
...this.workspaceMigrationFactory.createColumnActions(
WorkspaceMigrationColumnActionType.CREATE,
fieldMetadata,
),
},
];
);
}
workspaceMigrations.push({
workspaceId: fieldMetadata.workspaceId,
name: generateMigrationName(`create-${fieldMetadata.name}`),
workspaceId: objectMetadata.workspaceId,
name: generateMigrationName(
`create-${objectMetadata.nameSingular}-fields`,
),
isCustom: false,
migrations,
migrations: [
{
name: computeObjectTargetTable(
originalObjectMetadataMap[objectMetadataId],
),
action: WorkspaceMigrationTableActionType.ALTER,
columns,
},
],
});
}

View File

@ -282,6 +282,7 @@ export const NOTE_STANDARD_FIELD_IDS = {
attachments: '20202020-4986-4c92-bf19-39934b149b16',
timelineActivities: '20202020-7030-42f8-929c-1a57b25d6bce',
favorites: '20202020-4d1d-41ac-b13b-621631298d67',
searchVector: '20202020-7ea8-44d4-9d4c-51dd2a757950',
};
export const NOTE_TARGET_STANDARD_FIELD_IDS = {

View File

@ -75,8 +75,9 @@ const getColumnExpression = (
): string => {
const quotedColumnName = `"${columnName}"`;
if (fieldType === FieldMetadataType.EMAILS) {
return `
switch (fieldType) {
case FieldMetadataType.EMAILS:
return `
COALESCE(
replace(
${quotedColumnName},
@ -86,7 +87,9 @@ const getColumnExpression = (
''
)
`;
} else {
return `COALESCE(${quotedColumnName}, '')`;
case FieldMetadataType.RICH_TEXT:
return `COALESCE(jsonb_path_query_array(${quotedColumnName}::jsonb, '$[*].content[*]."text"'::jsonpath)::text, '')`;
default:
return `COALESCE(${quotedColumnName}, '')`;
}
};

View File

@ -6,6 +6,7 @@ const SEARCHABLE_FIELD_TYPES = [
FieldMetadataType.EMAILS,
FieldMetadataType.ADDRESS,
FieldMetadataType.LINKS,
FieldMetadataType.RICH_TEXT,
] as const;
export type SearchableFieldType = (typeof SEARCHABLE_FIELD_TYPES)[number];