Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(server): search unknown place #10866

Open
wants to merge 16 commits into
base: main
Choose a base branch
from

Conversation

jforseth210
Copy link

This is a rough draft for allowing users to search for photos that specifically don't have a location (or at least a country) as requested in #8362.

It updates the server to accept null as a value for country, which tells the database to search for assets with no country exifInfo.

The frontend is updated to automatically include an "Unknown" option in the country combo box, which is passed to the server as {"country":null}. The filter list in the results is also updated to display "Unknown" if the value of a filter is null.

I don't have a ton of experience contributing to FOSS, so this probably is a ways from merge ready. Let me know what I need to do differently.

  • I suspect there's something I need to update in /open-api but I'm not sure what.
  • Removing the validators in search.dto.ts makes me a bit nervous. Is there anything that's expecting a string that I missed?
  • I'd love some advice to make selectedOption easier to read
  • I haven't touched the mobile app at all

@jforseth210 jforseth210 changed the title Search unknown place [feat] Search unknown place Jul 4, 2024
@alextran1502 alextran1502 changed the title [feat] Search unknown place feat(server): search unknown place Jul 5, 2024
@jforseth210
Copy link
Author

I'm not really sure how to correctly update the types for @immich/sdk. Tried reading through the docs but still not getting it... Where's the best place to get a hand? Discord?

@danieldietzler
Copy link
Member

I'm not really sure how to correctly update the types for @immich/sdk. Tried reading through the docs but still not getting it... Where's the best place to get a hand? Discord?

make open-api. But yeah, generally joining our discord (https://discord.immich.app) is a good idea

@jforseth210
Copy link
Author

I think that last commit should fix those api issues. Thanks @danieldietzler and @jrasm91 for the help! What's next?

Copy link
Contributor

@jrasm91 jrasm91 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! I made a few changes, but I think it is good to go now:

  • Moved the logic to return "null" options to the server. This means they are only shown in the UI if there are actually valid results (given other criteria) with null values.
  • Updated the api to accept empty string or null. (The mobile app can't actually send null, and empty string makes the combobox types a lot simpler)
  • Added some e2e tests for searching with empty/null
  • Expanded the scope to include camera make, camera model, and camera lens.

Copy link
Member

@danieldietzler danieldietzler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jrasm91 jrasm91 requested a review from mertalev July 11, 2024 15:10
Copy link
Contributor

@mertalev mertalev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this! I think some of the backend behavior is strange and surprising for the sake of letting the frontend send '' instead of null. I'd much prefer if you could make the frontend send null instead.

.createQueryBuilder('exif')
.leftJoin('exif.asset', 'asset')
.where('asset.ownerId = :userId', { userId })
.andWhere('exif.country IS NOT NULL')
.select('exif.country')
.select('exif.country', 'exif_country')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a particular reason you set an alias here and make it a raw query? You can remove the alias and use getMany like the original, just removing the filter at the end.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, when I did that it only returned one result (United States) instead of two (United States, null).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, maybe because you don't select the id field. That's fine, it can be a raw query. Maybe just make the alias camel case (or remove it).

Comment on lines +52 to +53
if (value === null || value === '') {
builder.andWhere(`exifInfo.${key} IS NULL`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An empty string is not the same as null and shouldn't have this behavior.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could map it in the service instead, if you want, but at the API level it is going to mean the same thing.

Comment on lines +29 to +31
if (filters.make && !makes.includes(filters.make)) {
filters.make = undefined;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this necessary?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This just matches what was in the location filter file. If the current set filter isn't in the list of valid options it is discarded.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but when can that actually happen?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think only by directly navigating with those params. Just seemed good to make them consistent, but maybe it isn't necessary


@IsString()
@IsNotEmpty()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the request should explicitly be null and not an empty string, so this doesn't need to be removed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could do that, at least for the web. But the mobile app can't actually send null values through the generated client. So either the mobile app doesn't get this functionality or we need to use an empty string in the api to indicate querying for null.

@mertalev
Copy link
Contributor

The mobile app can't actually send null

How can it not send null? That's so weird. In that case I'd rather handle the '' => null conversion as a transformer without polluting other code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants