mirror of
https://github.com/immich-app/immich.git
synced 2025-03-11 02:23:09 -05:00
fix(server): search and explore part 2 (#2031)
* explore logging * chore: regenerate open api * fix: explore page
This commit is contained in:
parent
6e1d09fc32
commit
25a10784eb
7 changed files with 64 additions and 42 deletions
2
mobile/openapi/README.md
generated
2
mobile/openapi/README.md
generated
|
@ -3,7 +3,7 @@ Immich API
|
||||||
|
|
||||||
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||||
|
|
||||||
- API version: 1.51.0
|
- API version: 1.51.1
|
||||||
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {
|
||||||
} from '@app/domain';
|
} from '@app/domain';
|
||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
import _, { Dictionary } from 'lodash';
|
import _, { Dictionary } from 'lodash';
|
||||||
import { filter, firstValueFrom, from, map, mergeMap, toArray } from 'rxjs';
|
import { catchError, filter, firstValueFrom, from, map, mergeMap, of, toArray } from 'rxjs';
|
||||||
import { Client } from 'typesense';
|
import { Client } from 'typesense';
|
||||||
import { CollectionCreateSchema } from 'typesense/lib/Typesense/Collections';
|
import { CollectionCreateSchema } from 'typesense/lib/Typesense/Collections';
|
||||||
import { DocumentSchema, SearchResponse } from 'typesense/lib/Typesense/Documents';
|
import { DocumentSchema, SearchResponse } from 'typesense/lib/Typesense/Documents';
|
||||||
|
@ -148,7 +148,7 @@ export class TypesenseRepository implements ISearchRepository {
|
||||||
|
|
||||||
const common = {
|
const common = {
|
||||||
q: '*',
|
q: '*',
|
||||||
filter_by: `ownerId:${userId}`,
|
filter_by: this.buildFilterBy('ownerId', userId, true),
|
||||||
per_page: 100,
|
per_page: 100,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -157,8 +157,8 @@ export class TypesenseRepository implements ISearchRepository {
|
||||||
const { facet_counts: facets } = await asset$.search({
|
const { facet_counts: facets } = await asset$.search({
|
||||||
...common,
|
...common,
|
||||||
query_by: 'exifInfo.imageName',
|
query_by: 'exifInfo.imageName',
|
||||||
facet_by: this.getFacetFieldNames(SearchCollection.ASSETS),
|
facet_by: 'exifInfo.city,smartInfo.objects',
|
||||||
max_facet_values: 50,
|
max_facet_values: 12,
|
||||||
});
|
});
|
||||||
|
|
||||||
return firstValueFrom(
|
return firstValueFrom(
|
||||||
|
@ -166,23 +166,31 @@ export class TypesenseRepository implements ISearchRepository {
|
||||||
mergeMap(
|
mergeMap(
|
||||||
(facet) =>
|
(facet) =>
|
||||||
from(facet.counts).pipe(
|
from(facet.counts).pipe(
|
||||||
mergeMap(
|
mergeMap((count) => {
|
||||||
(count) =>
|
const config = {
|
||||||
from(
|
...common,
|
||||||
asset$.search({
|
query_by: 'exifInfo.imageName',
|
||||||
...common,
|
filter_by: [
|
||||||
query_by: 'exifInfo.imageName',
|
this.buildFilterBy('ownerId', userId, true),
|
||||||
filter_by: `${facet.field_name}:${count.value}`,
|
this.buildFilterBy(facet.field_name, count.value, true),
|
||||||
}),
|
].join(' && '),
|
||||||
).pipe(
|
per_page: 1,
|
||||||
map((result) => ({
|
};
|
||||||
value: count.value,
|
|
||||||
data: result.hits?.[0]?.document as AssetEntity,
|
this.logger.verbose(`Explore subquery: "filter_by:${config.filter_by}" (count:${count.count})`);
|
||||||
})),
|
|
||||||
filter((item) => !!item.data),
|
return from(asset$.search(config)).pipe(
|
||||||
),
|
catchError((error: any) => {
|
||||||
5,
|
this.logger.warn(`Explore subquery error: ${error}`, error?.stack);
|
||||||
),
|
return of({ hits: [] });
|
||||||
|
}),
|
||||||
|
map((result) => ({
|
||||||
|
value: count.value,
|
||||||
|
data: result.hits?.[0]?.document as AssetEntity,
|
||||||
|
})),
|
||||||
|
filter((item) => !!item.data),
|
||||||
|
);
|
||||||
|
}, 5),
|
||||||
toArray(),
|
toArray(),
|
||||||
map((items) => ({
|
map((items) => ({
|
||||||
fieldName: facet.field_name as string,
|
fieldName: facet.field_name as string,
|
||||||
|
@ -208,7 +216,7 @@ export class TypesenseRepository implements ISearchRepository {
|
||||||
await this.client
|
await this.client
|
||||||
.collections(schemaMap[collection].name)
|
.collections(schemaMap[collection].name)
|
||||||
.documents()
|
.documents()
|
||||||
.delete({ filter_by: `id: [${ids.join(',')}]` });
|
.delete({ filter_by: this.buildFilterBy('id', ids, true) });
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchAlbums(query: string, filters: SearchFilter): Promise<SearchResult<AlbumEntity>> {
|
async searchAlbums(query: string, filters: SearchFilter): Promise<SearchResult<AlbumEntity>> {
|
||||||
|
@ -350,18 +358,17 @@ export class TypesenseRepository implements ISearchRepository {
|
||||||
|
|
||||||
private getAlbumFilters(filters: SearchFilter) {
|
private getAlbumFilters(filters: SearchFilter) {
|
||||||
const { userId } = filters;
|
const { userId } = filters;
|
||||||
const _filters = [`ownerId:${userId}`];
|
|
||||||
|
const _filters = [this.buildFilterBy('ownerId', userId, true)];
|
||||||
|
|
||||||
if (filters.id) {
|
if (filters.id) {
|
||||||
_filters.push(`id:=${filters.id}`);
|
_filters.push(this.buildFilterBy('id', filters.id, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const item of albumSchema.fields || []) {
|
for (const item of albumSchema.fields || []) {
|
||||||
let value = filters[item.name as keyof SearchFilter];
|
const value = filters[item.name as keyof SearchFilter];
|
||||||
if (Array.isArray(value)) {
|
|
||||||
value = `[${value.join(',')}]`;
|
|
||||||
}
|
|
||||||
if (item.facet && value !== undefined) {
|
if (item.facet && value !== undefined) {
|
||||||
_filters.push(`${item.name}:${value}`);
|
_filters.push(this.buildFilterBy(item.name, value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,17 +380,17 @@ export class TypesenseRepository implements ISearchRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
private getAssetFilters(filters: SearchFilter) {
|
private getAssetFilters(filters: SearchFilter) {
|
||||||
const _filters = [`ownerId:${filters.userId}`];
|
const { userId } = filters;
|
||||||
|
const _filters = [this.buildFilterBy('ownerId', userId, true)];
|
||||||
|
|
||||||
if (filters.id) {
|
if (filters.id) {
|
||||||
_filters.push(`id:=${filters.id}`);
|
_filters.push(this.buildFilterBy('id', filters.id, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const item of assetSchema.fields || []) {
|
for (const item of assetSchema.fields || []) {
|
||||||
let value = filters[item.name as keyof SearchFilter];
|
const value = filters[item.name as keyof SearchFilter];
|
||||||
if (Array.isArray(value)) {
|
|
||||||
value = `[${value.join(',')}]`;
|
|
||||||
}
|
|
||||||
if (item.facet && value !== undefined) {
|
if (item.facet && value !== undefined) {
|
||||||
_filters.push(`${item.name}:${value}`);
|
_filters.push(this.buildFilterBy(item.name, value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,4 +400,19 @@ export class TypesenseRepository implements ISearchRepository {
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private buildFilterBy(key: string, values: boolean | string | string[], exact?: boolean) {
|
||||||
|
const token = exact ? ':=' : ':';
|
||||||
|
|
||||||
|
const _values = (Array.isArray(values) ? values : [values]).map((value) => {
|
||||||
|
if (typeof value === 'boolean' || value === 'true' || value === 'false') {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return '`' + value + '`';
|
||||||
|
});
|
||||||
|
|
||||||
|
const value = _values.length > 1 ? `[${_values.join(',')}]` : _values[0];
|
||||||
|
|
||||||
|
return `${key}${token}${value}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
2
web/src/api/open-api/api.ts
generated
2
web/src/api/open-api/api.ts
generated
|
@ -4,7 +4,7 @@
|
||||||
* Immich
|
* Immich
|
||||||
* Immich API
|
* Immich API
|
||||||
*
|
*
|
||||||
* The version of the OpenAPI document: 1.51.0
|
* The version of the OpenAPI document: 1.51.1
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
|
2
web/src/api/open-api/base.ts
generated
2
web/src/api/open-api/base.ts
generated
|
@ -4,7 +4,7 @@
|
||||||
* Immich
|
* Immich
|
||||||
* Immich API
|
* Immich API
|
||||||
*
|
*
|
||||||
* The version of the OpenAPI document: 1.51.0
|
* The version of the OpenAPI document: 1.51.1
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
|
2
web/src/api/open-api/common.ts
generated
2
web/src/api/open-api/common.ts
generated
|
@ -4,7 +4,7 @@
|
||||||
* Immich
|
* Immich
|
||||||
* Immich API
|
* Immich API
|
||||||
*
|
*
|
||||||
* The version of the OpenAPI document: 1.51.0
|
* The version of the OpenAPI document: 1.51.1
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
|
2
web/src/api/open-api/configuration.ts
generated
2
web/src/api/open-api/configuration.ts
generated
|
@ -4,7 +4,7 @@
|
||||||
* Immich
|
* Immich
|
||||||
* Immich API
|
* Immich API
|
||||||
*
|
*
|
||||||
* The version of the OpenAPI document: 1.51.0
|
* The version of the OpenAPI document: 1.51.1
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
|
2
web/src/api/open-api/index.ts
generated
2
web/src/api/open-api/index.ts
generated
|
@ -4,7 +4,7 @@
|
||||||
* Immich
|
* Immich
|
||||||
* Immich API
|
* Immich API
|
||||||
*
|
*
|
||||||
* The version of the OpenAPI document: 1.51.0
|
* The version of the OpenAPI document: 1.51.1
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
|
Loading…
Add table
Reference in a new issue