From 5a49de5592cfa5e40a85809de0b46a5cd3cc0123 Mon Sep 17 00:00:00 2001 From: Jason Rasmussen <jrasm91@gmail.com> Date: Sat, 27 Apr 2024 08:57:39 -0400 Subject: [PATCH] chore(server): remove old asset search (#9104) * chore(server): remove old asset search * chore: remove more unused search code --- mobile/openapi/README.md | Bin 26660 -> 26502 bytes mobile/openapi/doc/AssetApi.md | Bin 46195 -> 39094 bytes mobile/openapi/doc/SearchApi.md | Bin 17401 -> 14676 bytes mobile/openapi/lib/api/asset_api.dart | Bin 47965 -> 35922 bytes mobile/openapi/lib/api/search_api.dart | Bin 16129 -> 12851 bytes mobile/openapi/test/asset_api_test.dart | Bin 4769 -> 3820 bytes mobile/openapi/test/search_api_test.dart | Bin 1752 -> 1520 bytes open-api/immich-openapi-specs.json | 541 ------------------ open-api/typescript-sdk/src/fetch-client.ts | 180 +----- server/src/controllers/asset.controller.ts | 21 +- server/src/controllers/index.ts | 3 +- server/src/controllers/search.controller.ts | 9 +- server/src/dtos/search.dto.ts | 47 -- server/src/interfaces/asset.interface.ts | 5 - server/src/interfaces/search.interface.ts | 23 - server/src/queries/asset.repository.sql | 31 - server/src/repositories/asset.repository.ts | 90 --- server/src/services/search.service.spec.ts | 117 ---- server/src/services/search.service.ts | 57 +- .../repositories/asset.repository.mock.ts | 1 - 20 files changed, 30 insertions(+), 1095 deletions(-) diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index 187d8e8fa9ce92f965805d85bc763c10b1113140..a0872d6f97f5cdad7ee77418ca0b86d91e93cbfc 100644 GIT binary patch delta 19 bcmZ2-fwAp8<A%>7o83j%i*0t$d14I!TPFyW delta 85 zcmZoW&$#3Q<A%>7EQv+Q8IuhKrMZh!LCnPB;?$DK8-;}#izhn@iERETvQccZownHI k1KMoDnhG@vT3YU|AzE4r`VjS#1GGdZ>9B2Hr2WJi04h8kZ2$lO diff --git a/mobile/openapi/doc/AssetApi.md b/mobile/openapi/doc/AssetApi.md index 826e91a69066ca11d8cc5d44dc27c3d1a3622578..f335ca58681d1b31df4c5bdf3927c294b34345fa 100644 GIT binary patch delta 19 bcmezTf@#}ErVX=LHs4`UO50r7_DdH4WB&<> delta 2401 zcmeHI&u<$=6joZhF{!GiB&1N>uuhY1wcXUMK%!A;j8R-A6zWz*AQYmo@s8tZ*1Oj3 zIB6<G#jOZIF@t;Pt^Wa4q#h7LJ(MF79JwKJ;lP0ii4zCjd$Y5<Zp8(O8;8X2$M@d+ zc;9^c;QpRJe%<rc-CWKI8!h?6(8Ruok@?%uvpb*X?50XQnw+YtL^X<-h)y(Gtg#Vw z+qTi*VjKPkU0;M~gv=4ltu_S<6Yn+F3_>P<`r`Rz<~IVDxo>lq1(zMsvJLLSUsQ$l z`6eT~rZ5<;U57rt<Dq@Q*$hH17}{?Jf(JfYmjbcmSG~1vTb`9OH<=GPmqCHY*Fq=U zUV@fwX9KF*DjtL`ZVg(kbLf15d+d_ahP;lbZFQV=h;>*P1^$v7ff=$*&bCxGWD&o? zl#P~cL;}ujFBt;X^5f%^tqyM+qSbA$`40C~l?a`vm0VQpCD`qbEWKbXY_YYDf^Tur zO79501?DlhY1=@jcAYnsb(sYn5B7u6tHNn)?EF4AlN-|mGtL{@l=n^@KGeiJpdn%g zW{J_maa0Wz6UxHeaGaB)_4&OpZFztCy!`X_wPTM@7RnwEVZHopYeBx;JD#U0%Svyu zpoc80y;t|C$%0uN$&40U`B9IL>+wQ!PutY>m)^zwIA%!T55~sSPHF5I#_?nPbrmNb zK>VChE*nJaIx@rfz!=ehL52WUQ$&*n+m!~<IIav5T|_a3LRLZc?5Q&^(Yk)Ooi3P= z4G_yKlz)Rq;+3l+<o^162AEP2pc!J~N=Ma7DMJC0I*2%}5Xjqq+zZhevh<5ZqpB#S zw_L5im?u}hTc0~RKyN4<@Ug+uaf1x+RSOKrck1V!6Wbl!P&$yeAW(xVl5G0pG5r<* zp-pTX4-4ro=Xz65B~JsWRV?VY0em_#f{uC~=n|4%2p}iqjd}BbiA#B9XE+1m_Mb^y zP0vy(*1wZD5TThX`pb2u_=)^^JiiydPIA{Yh7HRiT?2ar?O4jd&7mt-ubd_w`^GHG zTVIys>Yamfw_L>E(I*59s^r6dP99%;hJfw<>@W!#bLDR3SSn@U$h-ZMTF$`D${A+A z>wj2CBn<mj?v!(+UEma8Yf7-dIRXx;m1ThjEL&EpR`R{Y;^-5q1T_b#MhO^c5X25a z3<ZeVSQb94A1f1PB0IW$R&*?D<%H57`TpYg^s>vEPS+EL2;igOM*@Uu1+O(LLa@{U z2xUYkUL0vOxOiUa3*_;{N=<H?R;()z&65WPbwmS6Gd?x#JbgIjx8^LVhdu#aP@*1i zNAi~0C}^r_T99T0{h3nsR87Z=7#%555}Iu()so#xiNu4nMBeL9?MEm{2|*`!ZaUu& L?R<Uhui3u=`9WtA diff --git a/mobile/openapi/doc/SearchApi.md b/mobile/openapi/doc/SearchApi.md index e4ab9ecfd3f0d626c2ff038606fc5f42e192ab46..b55bd067c20b933d686997d4cf11ac3ab640b465 100644 GIT binary patch delta 18 acmey_&UmG0!)?aRLQE+Vo1dtN$^!sXLI;Kb delta 603 zcmcao^s}9D!)-<_Ev;CM;MByT<P67xOugI`<zg^LQ=vvdOUvCgL`zFSA0o8*9Alxx z<k^O@ZW_rsnFTrux%nlT`FT1D1&QgYItqnARGL~;siRPonw*+fqN7lpSp^g?&P^-= za!M)-fSmHok_<<nU72O6DVrUb<yg4VGV>C16hH<}KBy+b4dH@Ko_s(}R0F~X*`Q#n zV4-JdVy&RBuaH-o3v?e;Zy`{oaB_l}xG+R9*cBi#kZVBVJP>h+vp}{$O$E6Rr>S6P zgA@xubc5UvR1Bmh$BRh_K?IS#161osrI4AdB_BSSkzZkQq<AU|IA|0#<T!xw0SOlc z4S5Y92NWp4*a5{8Fg&!hY7~I%===guq$K9VDsTZM3Mb1-D6>LB0?1;6h5^tx9iS{I p00@}?2?wACHlPNO?`0%Zcu@SUs9`*LzWLe7D-GUmwwDr>2LQ!H#y0=} diff --git a/mobile/openapi/lib/api/asset_api.dart b/mobile/openapi/lib/api/asset_api.dart index c6031f6bdaa6a607b32ed762bb7b8e3e7d9d1489..d477cf6bc904fb19183e9c69130b72882bc397ad 100644 GIT binary patch delta 14 Vcmccnjp@=1rVX}nn>~6(^#C`&23P<9 delta 5255 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 diff --git a/mobile/openapi/lib/api/search_api.dart b/mobile/openapi/lib/api/search_api.dart index 386a2f35368a42587ae3436d48abdee54a821541..15654fc066c21bc23b1a1f91057b2f3ddc250778 100644 GIT binary patch delta 12 TcmZpy+nln&UwpHy$`dI7BzOfM delta 1260 zcmdT^Jx{|h5LFQa0xFb=w&CLtAigZZMhQdJjY=Q}29OW~l+XszBu-Nhpce51nEWST zL(0m=Ut#1&;PWMr$n1#4KIh(Do}Zr`pFa*>_b0_$VN48)jry7IU!6en$_?yM0L!vy zgjG1ERL758-_w#_uX6&yY0D9x#d3k;c*J{7c&j0)P3SZoFVd2#P1n71v<#JXJEviU z&4;7gz!AGM=14tkw%u#zTm;N~ICP`-P80<V@4{cc2P~?o-LNDk`V8ccYKkv|gD7;p zRt<P2MCNG;QB6vaTbfX0eu^Zc(s%Ag5=ogc=!=cgo-k(LN8AfoMs<Z{Y|dk_#1y}k zm2IgsKwpiBBBqF2pim+y(6Lf@v2Ijn@BkzXCmqDG*A$m|{!0>fjDSUTY6!wFI*`;* zv?!EN3UsU#OVZk!lbT5sO7{y!ov3A0=P*DR&N@!2i(3@W#zZAAR90%_WoAFfhS_C& z3FX3nHu+0s@!=1Qo%Qv2&e+^q%ilVBJd#UChP4ypk~8h(-f<hR96b^=rB1RFN0Dc2 i<($MAa)JI}fcM{4Bb&}0v7K8ni1*B=p?H7tqw)pZc7S03 diff --git a/mobile/openapi/test/asset_api_test.dart b/mobile/openapi/test/asset_api_test.dart index e64d3acf5e2408a6a61534252367ba84d5c009aa..7c2d71baca5543c7488fdf6b4a0b1f7cc8a00e10 100644 GIT binary patch delta 16 YcmZ3e`bKucH?GNN+4(o`;(N{v077C1TL1t6 delta 688 zcmZXS%St0b6owZjBN)7Z8%Ggp1i?iXx*SFZBW55lUO;i<LaVz@(uY)6HC3k*GcNQM zq}H>THyH3ad=59R-D;&<tD|n3{{PeG>vMZt{kQ)AX~zAnEnQgPCQe$`0@;l#c1#9U zkHrbZeVeDvU?7bup>svX>pf0zf+?`rfPWROE`fP(yRG`7yPaiguVhfM79dVhfIi}s z1SkskJiENqF5^uWX)PJr_N7NEF5SZ1^4EP$s8xs^XzHkzjPlfdoBMGM%I<r%3`mKQ z;bznk!AW@^Dp7u1^nPdr7^cV15Z4BK=zskSB^>ayN_-2H^{YH(8SlY$ll?|Z+hwCa zSq8>x)e$xTGXn#J;k&jCSo{MOX{<tmB|p`Pd6F+*eH?OO?n3uWn<|r%JdG4bS(3w| z$Z(r{Uev4YDFvh$$;l{#_P9A3Wv)^Gem;aKD{;kchDb@v-wqDI4>(wRAi<x)gwwvn p?u0x7ok?G5$T%h*_d&Rw#!78`jBc~G<!-)AyZh<+yL#hc>IHp*_p|^2 diff --git a/mobile/openapi/test/search_api_test.dart b/mobile/openapi/test/search_api_test.dart index 801c97a180a4e00439a64bc9941d6ae0cfa2da25..a00b1290f44a5aace2d2a898397b30cf9ac5cf55 100644 GIT binary patch delta 12 Tcmcb?`+<AILFUaXS@f9zCFTU? delta 150 zcmeyseS>$yLFRgmYK5fy{2YbkoXi3p2s1aoBr`uxM<K5?SD_#=Jyk~`xTGjEFI}M! z!75EHs)Q;pN=;79D}g94&a46|2OC(Nn^*)Cg=#ISEPzRrXO?6*7A0q7mZhdBFxF09 Q$SON|0h7_@70ez?00!YTZ~y=R diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index d1e0b6aace..e831c6f3e7 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -1823,423 +1823,6 @@ ] } }, - "/assets": { - "get": { - "deprecated": true, - "operationId": "searchAssets", - "parameters": [ - { - "name": "checksum", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "city", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "country", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "createdAfter", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "createdBefore", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "deviceAssetId", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "deviceId", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "encodedVideoPath", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "id", - "required": false, - "in": "query", - "schema": { - "format": "uuid", - "type": "string" - } - }, - { - "name": "isArchived", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isEncoded", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isExternal", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isFavorite", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isMotion", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isNotInAlbum", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isOffline", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isReadOnly", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isVisible", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "lensModel", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "libraryId", - "required": false, - "in": "query", - "schema": { - "format": "uuid", - "type": "string" - } - }, - { - "name": "make", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "model", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "order", - "required": false, - "in": "query", - "schema": { - "$ref": "#/components/schemas/AssetOrder" - } - }, - { - "name": "originalFileName", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "originalPath", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "page", - "required": false, - "in": "query", - "schema": { - "minimum": 1, - "type": "number" - } - }, - { - "name": "personIds", - "required": false, - "in": "query", - "schema": { - "format": "uuid", - "type": "array", - "items": { - "type": "string" - } - } - }, - { - "name": "previewPath", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "resizePath", - "required": false, - "in": "query", - "deprecated": true, - "schema": { - "type": "string" - } - }, - { - "name": "size", - "required": false, - "in": "query", - "schema": { - "minimum": 1, - "maximum": 1000, - "type": "number" - } - }, - { - "name": "state", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "takenAfter", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "takenBefore", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "thumbnailPath", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "trashedAfter", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "trashedBefore", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "type", - "required": false, - "in": "query", - "schema": { - "$ref": "#/components/schemas/AssetTypeEnum" - } - }, - { - "name": "updatedAfter", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "updatedBefore", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "webpPath", - "required": false, - "in": "query", - "deprecated": true, - "schema": { - "type": "string" - } - }, - { - "name": "withArchived", - "required": false, - "in": "query", - "schema": { - "default": false, - "type": "boolean" - } - }, - { - "name": "withDeleted", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "withExif", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "withPeople", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "withStacked", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "items": { - "$ref": "#/components/schemas/AssetResponseDto" - }, - "type": "array" - } - } - }, - "description": "" - } - }, - "security": [ - { - "bearer": [] - }, - { - "cookie": [] - }, - { - "api_key": [] - } - ], - "tags": [ - "Asset" - ] - } - }, "/audit/deletes": { "get": { "operationId": "getAuditDeletes", @@ -4383,130 +3966,6 @@ ] } }, - "/search": { - "get": { - "deprecated": true, - "operationId": "search", - "parameters": [ - { - "name": "clip", - "required": false, - "in": "query", - "deprecated": true, - "schema": { - "type": "boolean" - } - }, - { - "name": "motion", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "page", - "required": false, - "in": "query", - "schema": { - "minimum": 1, - "type": "number" - } - }, - { - "name": "q", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "query", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "recent", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "size", - "required": false, - "in": "query", - "schema": { - "minimum": 1, - "maximum": 1000, - "type": "number" - } - }, - { - "name": "smart", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "type", - "required": false, - "in": "query", - "schema": { - "enum": [ - "IMAGE", - "VIDEO", - "AUDIO", - "OTHER" - ], - "type": "string" - } - }, - { - "name": "withArchived", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SearchResponseDto" - } - } - }, - "description": "" - } - }, - "security": [ - { - "bearer": [] - }, - { - "cookie": [] - }, - { - "api_key": [] - } - ], - "tags": [ - "Search" - ] - } - }, "/search/cities": { "get": { "operationId": "getAssetsByCity", diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index 2536afe598..378f77c54a 100644 --- a/open-api/typescript-sdk/src/fetch-client.ts +++ b/open-api/typescript-sdk/src/fetch-client.ts @@ -600,31 +600,6 @@ export type FileChecksumResponseDto = { export type FileReportFixDto = { items: FileReportItemDto[]; }; -export type SearchFacetCountResponseDto = { - count: number; - value: string; -}; -export type SearchFacetResponseDto = { - counts: SearchFacetCountResponseDto[]; - fieldName: string; -}; -export type SearchAlbumResponseDto = { - count: number; - facets: SearchFacetResponseDto[]; - items: AlbumResponseDto[]; - total: number; -}; -export type SearchAssetResponseDto = { - count: number; - facets: SearchFacetResponseDto[]; - items: AssetResponseDto[]; - nextPage: string | null; - total: number; -}; -export type SearchResponseDto = { - albums: SearchAlbumResponseDto; - assets: SearchAssetResponseDto; -}; export type SearchExploreItem = { data: AssetResponseDto; value: string; @@ -680,6 +655,31 @@ export type MetadataSearchDto = { withPeople?: boolean; withStacked?: boolean; }; +export type SearchFacetCountResponseDto = { + count: number; + value: string; +}; +export type SearchFacetResponseDto = { + counts: SearchFacetCountResponseDto[]; + fieldName: string; +}; +export type SearchAlbumResponseDto = { + count: number; + facets: SearchFacetResponseDto[]; + items: AlbumResponseDto[]; + total: number; +}; +export type SearchAssetResponseDto = { + count: number; + facets: SearchFacetResponseDto[]; + items: AssetResponseDto[]; + nextPage: string | null; + total: number; +}; +export type SearchResponseDto = { + albums: SearchAlbumResponseDto; + assets: SearchAssetResponseDto; +}; export type PlacesResponseDto = { admin1name?: string; admin2name?: string; @@ -1530,106 +1530,6 @@ export function updateAsset({ id, updateAssetDto }: { body: updateAssetDto }))); } -export function searchAssets({ checksum, city, country, createdAfter, createdBefore, deviceAssetId, deviceId, encodedVideoPath, id, isArchived, isEncoded, isExternal, isFavorite, isMotion, isNotInAlbum, isOffline, isReadOnly, isVisible, lensModel, libraryId, make, model, order, originalFileName, originalPath, page, personIds, previewPath, resizePath, size, state, takenAfter, takenBefore, thumbnailPath, trashedAfter, trashedBefore, $type, updatedAfter, updatedBefore, webpPath, withArchived, withDeleted, withExif, withPeople, withStacked }: { - checksum?: string; - city?: string; - country?: string; - createdAfter?: string; - createdBefore?: string; - deviceAssetId?: string; - deviceId?: string; - encodedVideoPath?: string; - id?: string; - isArchived?: boolean; - isEncoded?: boolean; - isExternal?: boolean; - isFavorite?: boolean; - isMotion?: boolean; - isNotInAlbum?: boolean; - isOffline?: boolean; - isReadOnly?: boolean; - isVisible?: boolean; - lensModel?: string; - libraryId?: string; - make?: string; - model?: string; - order?: AssetOrder; - originalFileName?: string; - originalPath?: string; - page?: number; - personIds?: string[]; - previewPath?: string; - resizePath?: string; - size?: number; - state?: string; - takenAfter?: string; - takenBefore?: string; - thumbnailPath?: string; - trashedAfter?: string; - trashedBefore?: string; - $type?: AssetTypeEnum; - updatedAfter?: string; - updatedBefore?: string; - webpPath?: string; - withArchived?: boolean; - withDeleted?: boolean; - withExif?: boolean; - withPeople?: boolean; - withStacked?: boolean; -}, opts?: Oazapfts.RequestOpts) { - return oazapfts.ok(oazapfts.fetchJson<{ - status: 200; - data: AssetResponseDto[]; - }>(`/assets${QS.query(QS.explode({ - checksum, - city, - country, - createdAfter, - createdBefore, - deviceAssetId, - deviceId, - encodedVideoPath, - id, - isArchived, - isEncoded, - isExternal, - isFavorite, - isMotion, - isNotInAlbum, - isOffline, - isReadOnly, - isVisible, - lensModel, - libraryId, - make, - model, - order, - originalFileName, - originalPath, - page, - personIds, - previewPath, - resizePath, - size, - state, - takenAfter, - takenBefore, - thumbnailPath, - trashedAfter, - trashedBefore, - "type": $type, - updatedAfter, - updatedBefore, - webpPath, - withArchived, - withDeleted, - withExif, - withPeople, - withStacked - }))}`, { - ...opts - })); -} export function getAuditDeletes({ after, entityType, userId }: { after: string; entityType: EntityType; @@ -2201,36 +2101,6 @@ export function fixAuditFiles({ fileReportFixDto }: { body: fileReportFixDto }))); } -export function search({ clip, motion, page, q, query, recent, size, smart, $type, withArchived }: { - clip?: boolean; - motion?: boolean; - page?: number; - q?: string; - query?: string; - recent?: boolean; - size?: number; - smart?: boolean; - $type?: "IMAGE" | "VIDEO" | "AUDIO" | "OTHER"; - withArchived?: boolean; -}, opts?: Oazapfts.RequestOpts) { - return oazapfts.ok(oazapfts.fetchJson<{ - status: 200; - data: SearchResponseDto; - }>(`/search${QS.query(QS.explode({ - clip, - motion, - page, - q, - query, - recent, - size, - smart, - "type": $type, - withArchived - }))}`, { - ...opts - })); -} export function getAssetsByCity(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; diff --git a/server/src/controllers/asset.controller.ts b/server/src/controllers/asset.controller.ts index 8e446d23f9..9db27998d2 100644 --- a/server/src/controllers/asset.controller.ts +++ b/server/src/controllers/asset.controller.ts @@ -1,5 +1,5 @@ import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common'; -import { ApiOperation, ApiTags } from '@nestjs/swagger'; +import { ApiTags } from '@nestjs/swagger'; import { AssetResponseDto, MemoryLaneResponseDto } from 'src/dtos/asset-response.dto'; import { AssetBulkDeleteDto, @@ -12,30 +12,13 @@ import { UpdateAssetDto, } from 'src/dtos/asset.dto'; import { AuthDto } from 'src/dtos/auth.dto'; -import { MapMarkerDto, MapMarkerResponseDto, MemoryLaneDto, MetadataSearchDto } from 'src/dtos/search.dto'; +import { MapMarkerDto, MapMarkerResponseDto, MemoryLaneDto } from 'src/dtos/search.dto'; import { UpdateStackParentDto } from 'src/dtos/stack.dto'; import { Auth, Authenticated, SharedLinkRoute } from 'src/middleware/auth.guard'; import { Route } from 'src/middleware/file-upload.interceptor'; import { AssetService } from 'src/services/asset.service'; -import { SearchService } from 'src/services/search.service'; import { UUIDParamDto } from 'src/validation'; -@ApiTags('Asset') -@Controller('assets') -@Authenticated() -export class AssetsController { - constructor(private searchService: SearchService) {} - - @Get() - @ApiOperation({ deprecated: true }) - async searchAssets(@Auth() auth: AuthDto, @Query() dto: MetadataSearchDto): Promise<AssetResponseDto[]> { - const { - assets: { items }, - } = await this.searchService.searchMetadata(auth, dto); - return items; - } -} - @ApiTags('Asset') @Controller(Route.ASSET) @Authenticated() diff --git a/server/src/controllers/index.ts b/server/src/controllers/index.ts index bd10c41a43..df1a44a157 100644 --- a/server/src/controllers/index.ts +++ b/server/src/controllers/index.ts @@ -3,7 +3,7 @@ import { AlbumController } from 'src/controllers/album.controller'; import { APIKeyController } from 'src/controllers/api-key.controller'; import { AppController } from 'src/controllers/app.controller'; import { AssetControllerV1 } from 'src/controllers/asset-v1.controller'; -import { AssetController, AssetsController } from 'src/controllers/asset.controller'; +import { AssetController } from 'src/controllers/asset.controller'; import { AuditController } from 'src/controllers/audit.controller'; import { AuthController } from 'src/controllers/auth.controller'; import { DownloadController } from 'src/controllers/download.controller'; @@ -34,7 +34,6 @@ export const controllers = [ AppController, AssetController, AssetControllerV1, - AssetsController, AuditController, AuthController, DownloadController, diff --git a/server/src/controllers/search.controller.ts b/server/src/controllers/search.controller.ts index eaf45be293..ce0d0f646d 100644 --- a/server/src/controllers/search.controller.ts +++ b/server/src/controllers/search.controller.ts @@ -1,12 +1,11 @@ import { Body, Controller, Get, HttpCode, HttpStatus, Post, Query } from '@nestjs/common'; -import { ApiOperation, ApiTags } from '@nestjs/swagger'; +import { ApiTags } from '@nestjs/swagger'; import { AssetResponseDto } from 'src/dtos/asset-response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { PersonResponseDto } from 'src/dtos/person.dto'; import { MetadataSearchDto, PlacesResponseDto, - SearchDto, SearchExploreResponseDto, SearchPeopleDto, SearchPlacesDto, @@ -23,12 +22,6 @@ import { SearchService } from 'src/services/search.service'; export class SearchController { constructor(private service: SearchService) {} - @Get() - @ApiOperation({ deprecated: true }) - search(@Auth() auth: AuthDto, @Query() dto: SearchDto): Promise<SearchResponseDto> { - return this.service.search(auth, dto); - } - @Post('metadata') @HttpCode(HttpStatus.OK) searchMetadata(@Auth() auth: AuthDto, @Body() dto: MetadataSearchDto): Promise<SearchResponseDto> { diff --git a/server/src/dtos/search.dto.ts b/server/src/dtos/search.dto.ts index d96ce0d98a..3304aae8cf 100644 --- a/server/src/dtos/search.dto.ts +++ b/server/src/dtos/search.dto.ts @@ -199,53 +199,6 @@ export class SmartSearchDto extends BaseSearchDto { query!: string; } -// TODO: remove after implementing new search filters -/** @deprecated */ -export class SearchDto { - @IsString() - @IsNotEmpty() - @Optional() - q?: string; - - @IsString() - @IsNotEmpty() - @Optional() - query?: string; - - @ValidateBoolean({ optional: true }) - smart?: boolean; - - /** @deprecated */ - @ValidateBoolean({ optional: true }) - clip?: boolean; - - @IsEnum(AssetType) - @Optional() - type?: AssetType; - - @ValidateBoolean({ optional: true }) - recent?: boolean; - - @ValidateBoolean({ optional: true }) - motion?: boolean; - - @ValidateBoolean({ optional: true }) - withArchived?: boolean; - - @IsInt() - @Min(1) - @Type(() => Number) - @Optional() - page?: number; - - @IsInt() - @Min(1) - @Max(1000) - @Type(() => Number) - @Optional() - size?: number; -} - export class SearchPlacesDto { @IsString() @IsNotEmpty() diff --git a/server/src/interfaces/asset.interface.ts b/server/src/interfaces/asset.interface.ts index 9c2ebe3e73..fb6345df7c 100644 --- a/server/src/interfaces/asset.interface.ts +++ b/server/src/interfaces/asset.interface.ts @@ -129,10 +129,6 @@ export interface AssetExploreOptions extends AssetExploreFieldOptions { unnest?: boolean; } -export interface MetadataSearchOptions { - numResults: number; -} - export interface AssetFullSyncOptions { ownerId: string; lastCreationDate?: Date; @@ -188,7 +184,6 @@ export interface IAssetRepository { upsertJobStatus(jobStatus: Partial<AssetJobStatusEntity>): Promise<void>; getAssetIdByCity(userId: string, options: AssetExploreFieldOptions): Promise<SearchExploreItem<string>>; getAssetIdByTag(userId: string, options: AssetExploreFieldOptions): Promise<SearchExploreItem<string>>; - searchMetadata(query: string, userIds: string[], options: MetadataSearchOptions): Promise<AssetEntity[]>; getAllForUserFullSync(options: AssetFullSyncOptions): Promise<AssetEntity[]>; getChangedDeltaSync(options: AssetDeltaSyncOptions): Promise<AssetEntity[]>; } diff --git a/server/src/interfaces/search.interface.ts b/server/src/interfaces/search.interface.ts index 771b23e9c9..14c70631d6 100644 --- a/server/src/interfaces/search.interface.ts +++ b/server/src/interfaces/search.interface.ts @@ -5,29 +5,6 @@ import { Paginated } from 'src/utils/pagination'; export const ISearchRepository = 'ISearchRepository'; -export enum SearchStrategy { - SMART = 'SMART', - TEXT = 'TEXT', -} - -export interface SearchFilter { - id?: string; - userId: string; - type?: AssetType; - isFavorite?: boolean; - isArchived?: boolean; - city?: string; - state?: string; - country?: string; - make?: string; - model?: string; - objects?: string[]; - tags?: string[]; - recent?: boolean; - motion?: boolean; - debug?: boolean; -} - export interface SearchResult<T> { /** total matches */ total: number; diff --git a/server/src/queries/asset.repository.sql b/server/src/queries/asset.repository.sql index 86e9796faa..81dce80d0f 100644 --- a/server/src/queries/asset.repository.sql +++ b/server/src/queries/asset.repository.sql @@ -738,37 +738,6 @@ WHERE LIMIT 12 --- AssetRepository.searchMetadata -SELECT - asset.*, - e.*, - COALESCE("si"."tags", array[]::text[]) AS "tags", - COALESCE("si"."objects", array[]::text[]) AS "objects" -FROM - "assets" "asset" - INNER JOIN "exif" "e" ON asset."id" = e."assetId" - LEFT JOIN "smart_info" "si" ON si."assetId" = asset."id" -WHERE - ( - "asset"."isVisible" = true - AND "asset"."ownerId" IN ($1) - AND "asset"."isArchived" = $2 - AND ( - ( - e."exifTextSearchableColumn" || COALESCE( - si."smartInfoTextSearchableColumn", - to_tsvector('english', '') - ) - ) @@ PLAINTO_TSQUERY('english', $3) - OR asset."originalFileName" = $4 - ) - ) - AND ("asset"."deletedAt" IS NULL) -ORDER BY - "asset"."fileCreatedAt" DESC -LIMIT - 250 - -- AssetRepository.getAllForUserFullSync SELECT "asset"."id" AS "asset_id", diff --git a/server/src/repositories/asset.repository.ts b/server/src/repositories/asset.repository.ts index ddc666edd3..e2ec6b3274 100644 --- a/server/src/repositories/asset.repository.ts +++ b/server/src/repositories/asset.repository.ts @@ -1,6 +1,5 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import path from 'node:path'; import { Chunked, ChunkedArray, DummyValue, GenerateSql } from 'src/decorators'; import { AlbumEntity, AssetOrder } from 'src/entities/album.entity'; import { AssetJobStatusEntity } from 'src/entities/asset-job-status.entity'; @@ -23,7 +22,6 @@ import { LivePhotoSearchOptions, MapMarker, MapMarkerSearchOptions, - MetadataSearchOptions, MonthDay, TimeBucketItem, TimeBucketOptions, @@ -700,94 +698,6 @@ export class AssetRepository implements IAssetRepository { return builder; } - @GenerateSql({ params: [DummyValue.STRING, [DummyValue.UUID], { numResults: 250 }] }) - async searchMetadata( - query: string, - userIds: string[], - { numResults }: MetadataSearchOptions, - ): Promise<AssetEntity[]> { - const rows = await this.getBuilder({ - userIds: userIds, - exifInfo: false, - isArchived: false, - }) - .select('asset.*') - .addSelect('e.*') - .addSelect('COALESCE(si.tags, array[]::text[])', 'tags') - .addSelect('COALESCE(si.objects, array[]::text[])', 'objects') - .innerJoin('exif', 'e', 'asset."id" = e."assetId"') - .leftJoin('smart_info', 'si', 'si."assetId" = asset."id"') - .andWhere( - new Brackets((qb) => { - qb.where( - `(e."exifTextSearchableColumn" || COALESCE(si."smartInfoTextSearchableColumn", to_tsvector('english', ''))) - @@ PLAINTO_TSQUERY('english', :query)`, - { query }, - ).orWhere('asset."originalFileName" = :path', { path: path.parse(query).name }); - }), - ) - .addOrderBy('asset.fileCreatedAt', 'DESC') - .limit(numResults) - .getRawMany(); - - return rows.map( - ({ - tags, - objects, - country, - state, - city, - description, - model, - make, - dateTimeOriginal, - exifImageHeight, - exifImageWidth, - exposureTime, - fNumber, - fileSizeInByte, - focalLength, - iso, - latitude, - lensModel, - longitude, - modifyDate, - projectionType, - timeZone, - ...assetInfo - }) => - ({ - exifInfo: { - city, - country, - dateTimeOriginal, - description, - exifImageHeight, - exifImageWidth, - exposureTime, - fNumber, - fileSizeInByte, - focalLength, - iso, - latitude, - lensModel, - longitude, - make, - model, - modifyDate, - projectionType, - state, - timeZone, - }, - smartInfo: { - tags, - objects, - }, - ...assetInfo, - }) as AssetEntity, - ); - } - @GenerateSql({ params: [ { diff --git a/server/src/services/search.service.spec.ts b/server/src/services/search.service.spec.ts index a81ea87973..bf4cd7c679 100644 --- a/server/src/services/search.service.spec.ts +++ b/server/src/services/search.service.spec.ts @@ -1,6 +1,4 @@ import { mapAsset } from 'src/dtos/asset-response.dto'; -import { SearchDto } from 'src/dtos/search.dto'; -import { SystemConfigKey } from 'src/entities/system-config.entity'; import { IAssetRepository } from 'src/interfaces/asset.interface'; import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface'; @@ -97,119 +95,4 @@ describe(SearchService.name, () => { expect(result).toEqual(expectedResponse); }); }); - - describe('search', () => { - it('should throw an error if query is missing', async () => { - await expect(sut.search(authStub.user1, { q: '' })).rejects.toThrow('Missing query'); - }); - - it('should search by metadata if `clip` option is false', async () => { - const dto: SearchDto = { q: 'test query', clip: false }; - assetMock.searchMetadata.mockResolvedValueOnce([assetStub.image]); - partnerMock.getAll.mockResolvedValueOnce([]); - const expectedResponse = { - albums: { - total: 0, - count: 0, - items: [], - facets: [], - }, - assets: { - total: 1, - count: 1, - items: [mapAsset(assetStub.image)], - facets: [], - nextPage: null, - }, - }; - - const result = await sut.search(authStub.user1, dto); - - expect(result).toEqual(expectedResponse); - expect(assetMock.searchMetadata).toHaveBeenCalledWith(dto.q, [authStub.user1.user.id], { numResults: 250 }); - expect(searchMock.searchSmart).not.toHaveBeenCalled(); - }); - - it('should search archived photos if `withArchived` option is true', async () => { - const dto: SearchDto = { q: 'test query', clip: true, withArchived: true }; - const embedding = [1, 2, 3]; - searchMock.searchSmart.mockResolvedValueOnce({ items: [assetStub.image], hasNextPage: false }); - machineMock.encodeText.mockResolvedValueOnce(embedding); - partnerMock.getAll.mockResolvedValueOnce([]); - const expectedResponse = { - albums: { - total: 0, - count: 0, - items: [], - facets: [], - }, - assets: { - total: 1, - count: 1, - items: [mapAsset(assetStub.image)], - facets: [], - nextPage: null, - }, - }; - - const result = await sut.search(authStub.user1, dto); - - expect(result).toEqual(expectedResponse); - expect(searchMock.searchSmart).toHaveBeenCalledWith( - { page: 1, size: 100 }, - { - userIds: [authStub.user1.user.id], - embedding, - withArchived: true, - }, - ); - expect(assetMock.searchMetadata).not.toHaveBeenCalled(); - }); - - it('should search by CLIP if `clip` option is true', async () => { - const dto: SearchDto = { q: 'test query', clip: true }; - const embedding = [1, 2, 3]; - searchMock.searchSmart.mockResolvedValueOnce({ items: [assetStub.image], hasNextPage: false }); - machineMock.encodeText.mockResolvedValueOnce(embedding); - partnerMock.getAll.mockResolvedValueOnce([]); - const expectedResponse = { - albums: { - total: 0, - count: 0, - items: [], - facets: [], - }, - assets: { - total: 1, - count: 1, - items: [mapAsset(assetStub.image)], - facets: [], - nextPage: null, - }, - }; - - const result = await sut.search(authStub.user1, dto); - - expect(result).toEqual(expectedResponse); - expect(searchMock.searchSmart).toHaveBeenCalledWith( - { page: 1, size: 100 }, - { - userIds: [authStub.user1.user.id], - embedding, - withArchived: false, - }, - ); - expect(assetMock.searchMetadata).not.toHaveBeenCalled(); - }); - - it.each([ - { key: SystemConfigKey.MACHINE_LEARNING_ENABLED }, - { key: SystemConfigKey.MACHINE_LEARNING_CLIP_ENABLED }, - ])('should throw an error if clip is requested but disabled', async ({ key }) => { - const dto: SearchDto = { q: 'test query', clip: true }; - configMock.load.mockResolvedValue([{ key, value: false }]); - - await expect(sut.search(authStub.user1, dto)).rejects.toThrow('Smart search is not enabled'); - }); - }); }); diff --git a/server/src/services/search.service.ts b/server/src/services/search.service.ts index b8e9f13fa6..d2636b91cf 100644 --- a/server/src/services/search.service.ts +++ b/server/src/services/search.service.ts @@ -6,7 +6,6 @@ import { PersonResponseDto } from 'src/dtos/person.dto'; import { MetadataSearchDto, PlacesResponseDto, - SearchDto, SearchPeopleDto, SearchPlacesDto, SearchResponseDto, @@ -23,7 +22,7 @@ import { IMachineLearningRepository } from 'src/interfaces/machine-learning.inte import { IMetadataRepository } from 'src/interfaces/metadata.interface'; import { IPartnerRepository } from 'src/interfaces/partner.interface'; import { IPersonRepository } from 'src/interfaces/person.interface'; -import { ISearchRepository, SearchExploreItem, SearchStrategy } from 'src/interfaces/search.interface'; +import { ISearchRepository, SearchExploreItem } from 'src/interfaces/search.interface'; import { ISystemConfigRepository } from 'src/interfaces/system-config.interface'; @Injectable() @@ -145,60 +144,6 @@ export class SearchService { } } - // TODO: remove after implementing new search filters - /** @deprecated */ - async search(auth: AuthDto, dto: SearchDto): Promise<SearchResponseDto> { - await this.configCore.requireFeature(FeatureFlag.SEARCH); - const { machineLearning } = await this.configCore.getConfig(); - const query = dto.q || dto.query; - if (!query) { - throw new Error('Missing query'); - } - - let strategy = SearchStrategy.TEXT; - if (dto.smart || dto.clip) { - await this.configCore.requireFeature(FeatureFlag.SMART_SEARCH); - strategy = SearchStrategy.SMART; - } - - const userIds = await this.getUserIdsToSearch(auth); - const page = dto.page ?? 1; - - let nextPage: string | null = null; - let assets: AssetEntity[] = []; - switch (strategy) { - case SearchStrategy.SMART: { - const embedding = await this.machineLearning.encodeText( - machineLearning.url, - { text: query }, - machineLearning.clip, - ); - - const { hasNextPage, items } = await this.searchRepository.searchSmart( - { page, size: dto.size || 100 }, - { - userIds, - embedding, - withArchived: !!dto.withArchived, - }, - ); - if (hasNextPage) { - nextPage = (page + 1).toString(); - } - assets = items; - break; - } - case SearchStrategy.TEXT: { - assets = await this.assetRepository.searchMetadata(query, userIds, { numResults: dto.size || 250 }); - } - default: { - break; - } - } - - return this.mapResponse(assets, nextPage); - } - private async getUserIdsToSearch(auth: AuthDto): Promise<string[]> { const userIds: string[] = [auth.user.id]; const partners = await this.partnerRepository.getAll(auth.user.id); diff --git a/server/test/repositories/asset.repository.mock.ts b/server/test/repositories/asset.repository.mock.ts index 694fc87cc2..f09d6b619e 100644 --- a/server/test/repositories/asset.repository.mock.ts +++ b/server/test/repositories/asset.repository.mock.ts @@ -35,7 +35,6 @@ export const newAssetRepositoryMock = (): Mocked<IAssetRepository> => { softDeleteAll: vitest.fn(), getAssetIdByCity: vitest.fn(), getAssetIdByTag: vitest.fn(), - searchMetadata: vitest.fn(), getAllForUserFullSync: vitest.fn(), getChangedDeltaSync: vitest.fn(), };