✅ Asset search support

This feature request covers search by

  • captured-at time
  • file type
  • filesystem path (for any asset file variant)
  • keyword
  • camera
  • lens
  • deleted
  • hidden
  • excluded
  • faved

sorted by

  • captured-at time, ascending
  • captured-at time, descending
  • most-recently-imported


Advanced search support to be added in another iteration:

(taken from the What’s Next page)
(edited by @mrm to include more fields, details, and documentation)

I think this one is pretty critical to take Photostructure from being a cool way to explore my photos to being a tool that I can use to find specific photos. As it stands, if I want to find photos of “Sam Whatshisface”, I have two options:

  • go to the Keywords page and scroll down through the hundreds of alphabetically sorted Keywords until I get to “Sam Whatshisface”


  • try to find a recent photo that has Sam in it, and then use the context streams to pull up the “Sam Whatshisface” stream

Expanding on this, searching REALLY becomes useful when you can search for photos that have multiple matching keywords. Being able to find all photos of Sam AND myself is a fantastic tool!

1 Like

I think this feature is a must-have. I would like to click a Search button and instantly find the keyword or date or place that I put into the metadata before. Use Adobe Lightroom Classic as an example of the nearly great metadata searching capabilities

1 Like

Thanks for the pointer!

As I have already voted for facial/object recognition, I would like to be able to search for a person or object.

I would like the ability to do multi AND and OR searches


This is one of the most voted-for features: I started work on it yesterday. :tada:

(edit: updated top post with usage information)


Thanks for starting working on it. Can’t wait… How do you plan to handle terms with spaces or colons?

The query parser will look for double or single quotes, so who:"Sam whatshisface" will work.

1 Like


:flight_departure: I’ve got the grammar nailed down.

Update 2021-03-24: I was able to add before: and after: namespaces, but as the MATCH operator doesn’t have a NOT MATCH sibling, I had to remove the - query negation from the grammar.

Update 2021-03-24: OMG I figured out how to do negation, but only for namespaced query terms.

Update 2021-04-10: The grammar has changed sufficiently to delete most of this post: see the instructions on the website instead.


I was able to add --query support to the list tool, so queries are going to be available to both the UI and the CLI:

$ ./photostructure list --help
Usage: list [options]

List paths in a Library.

  --query <TERMS...>   Apply the given query and return all matching asset file
                       paths. Must be the last argument. Incompatible with
  -j --json            Emit a JSON object for every asset file with "hidden"
                       and "shown" flags
  --dump               Emit a JSON object that includes all column values
  --where <WHERE>      Apply a SQL WHERE clause to filter the rows returned.
                       (default: "")
  --orderby <ORDERBY>  Apply a SQL ORDER BY clause to filter the rows returned.
                       (default: "")

I had a bit of a hitch in my search giddyup: SQLite doesn’t support multiple MATCH clauses, so I had to teach PhotoStructure how to condense these queries down to disjunctive normal form. This seems like it works now, and I’m building out the frontend now.

If you’ve emailed me logs or asked for support for the last day or two, know that I’ll be getting to your message soon.

1 Like

Have you considered using INTERSECT instead? Then you could use one MATCH per subquery

I may be misunderstanding you, but this would still mean I have to reduce to conjunctive normal form (rather than disjunctive normal form), right?

FWIW, I’ve got the SQL generator working…

Well, I assumed you have multiple AND conditions that’s why I suggested INTERSECT but I think if you rewrite the generating code to use INTERSECT for AND clause and UNION ALL for OR clause, you don’t need to convert to any normal forms and use it as is. But obviously my idea requires at least performance check

1 Like

Yeah, if UNION turns out to have horrible performance, I will certainly try INTERSECT. Thanks!

Goodness knows that I’ve been surprised by seemingly equivalent SQL that was 10x+ faster (especially when query planner wasn’t very sophisticated).

1 Like

Have you tried to do UNION ALL and then DISTINCT at the end of the query? They say UNION ALL has better performance than just UNION

1 Like

I’ll check that out, thanks.

@mrm I’ve checked the documentation for your search feature and it looks really awesome. I suggest to consider more convenient syntax for date ranges which, in my opinion, going to be one of the most used filters.

Please also consider some libraries for parsing dates like date:"last Friday"

For example Sugar - Home or GitHub - wanasit/chrono: A natural language date parser in Javascript

I would be nice if you also think how to fix one annoying issue all DAMs have. If you have hierarchical keywords a/b/c and you look for a/b there should be a way to distinguish cases when you want to find exactly that keyword without its descendants. Maybe it could be solved by kw:a/b AND -kw:a/b/* but it would be nice to have neater syntax for that case

This is interesting to me, because I actually don’t think I’ll use date ranges very much. I’m much more interested in searching by people and keywords, especially in combination.

Obviously neither of us is right or wrong, but it does underscore that there are lots of different preferred use cases.

1 Like