Skip to content

Conversation

@paul43210
Copy link

Pull Request: Photo EXIF Metadata Search Support

Title: feat(search): Add photo EXIF metadata to search index and WebDAV results


Description

This PR adds support for photo EXIF metadata in the Bleve search index and WebDAV REPORT responses. Photo metadata fields are now indexed, searchable via KQL queries, and returned in WebDAV search results.

This enables web extensions and applications to:

  • Build photo timeline views grouped by capture date
  • Filter photos by camera make/model
  • Display EXIF information (aperture, ISO, focal length, etc.)
  • Show geotagged photos on a map

Changes Summary

File Changes
ocis-pkg/kql/dictionary.peg Added photo keyword to KQL grammar
ocis-pkg/kql/dictionary_gen.go Regenerated parser
services/search/pkg/engine/bleve.go Added explicit field mappings with Store=true for photo fields
services/search/pkg/query/bleve/compiler.go Added photo field mappings to KQL compiler
services/search/pkg/query/bleve/compiler_test.go Added unit tests for photo queries
services/search/pkg/search/service.go Include photo metadata in search results
services/webdav/pkg/service/v0/search.go Added oc:photo-* WebDAV properties

Related Issue

  • This is a new feature enhancement (no existing issue)
  • Related discussion: Photo management is a common use case for personal cloud storage, and exposing EXIF metadata through search enables rich photo gallery experiences similar to Google Photos or Apple Photos.

Motivation and Context

oCIS already extracts and stores photo EXIF metadata via Tika during indexing, but this data was not:

  1. Stored in the Bleve index (fields lacked Store=true)
  2. Exposed through KQL query syntax
  3. Returned in WebDAV search results

This PR addresses all three gaps, enabling photo-centric applications to be built on oCIS.

Use Case Example

I've built a photo gallery web extension (ocis-photo-addon) that uses these APIs to:

  • Display photos in a timeline grouped by EXIF capture date
  • Show camera information in a lightbox viewer
  • Link to map locations for geotagged photos

How Has This Been Tested?

Test Environment

  • oCIS 7.3.1+dev (custom build with these changes)
  • Ubuntu 24.04 server
  • Tika 2.x for EXIF extraction
  • ~5,000 indexed photos

Test Cases

1. KQL Date Range Query

curl -u 'user:pass' \
  'https://cloud.example.com/dav/spaces/SPACE_ID' \
  -X REPORT -H "Content-Type: application/xml" \
  -d '<?xml version="1.0"?>
  <oc:search-files xmlns:oc="http://owncloud.org/ns">
    <oc:search>
      <oc:pattern>mediatype:image* AND photo.takenDateTime&gt;=2025-01-01 AND photo.takenDateTime&lt;=2025-12-31</oc:pattern>
      <oc:limit>100</oc:limit>
    </oc:search>
  </oc:search-files>'

2. KQL Camera Filter Query

# Find all photos taken with a Canon camera
<oc:pattern>mediatype:image* AND photo.cameraMake:Canon</oc:pattern>

3. WebDAV Response Verification Response includes photo properties:

<d:response>
  <d:href>/dav/spaces/.../photo.jpg</d:href>
  <d:propstat>
    <d:prop>
      <oc:photo-taken-date-time>2025-06-15T14:30:00Z</oc:photo-taken-date-time>
      <oc:photo-camera-make>Canon</oc:photo-camera-make>
      <oc:photo-camera-model>EOS R5</oc:photo-camera-model>
      <oc:photo-f-number>2.8</oc:photo-f-number>
      <oc:photo-iso>400</oc:photo-iso>
      <oc:photo-focal-length>85</oc:photo-focal-length>
      <oc:photo-location-latitude>43.6532</oc:photo-location-latitude>
      <oc:photo-location-longitude>-79.3832</oc:photo-location-longitude>
    </d:prop>
  </d:propstat>
</d:response>

4. Unit Tests

go test ./services/search/pkg/query/bleve/... -v

All new tests pass for photo field queries.

Screenshots

N/A - Backend/API changes only. However, the photo-addon extension demonstrates the UI possibilities this enables.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Technical debt
  • Tests only (no source changes)

Checklist

  • Code changes
  • Unit tests added
  • Acceptance tests added
  • Documentation ticket raised: (to be created if PR is accepted)

Additional Notes

Key Implementation Detail

The critical fix was adding explicit field mappings with Store=true in bleve.go. Without this, Bleve indexes the fields for searching but doesn't store the values for retrieval:

photoTakenDateTimeMapping := bleve.NewDateTimeFieldMapping()
photoTakenDateTimeMapping.Store = true
photoTakenDateTimeMapping.Name = "Photo.TakenDateTime"

Backward Compatibility

  • No breaking changes to existing APIs
  • Existing searches continue to work unchanged
  • Photo fields are simply additional data in responses
  • Users need to reindex to populate photo metadata in existing indexes

Future Considerations

  • This could be extended to support video metadata
  • Face detection/recognition could use similar patterns
  • Album/collection grouping could build on this foundation
# Pull Request: Photo EXIF Metadata Search Support

Title: feat(search): Add photo EXIF metadata to search index and WebDAV results


Description

This PR adds support for photo EXIF metadata in the Bleve search index and WebDAV REPORT responses. Photo metadata fields are now indexed, searchable via KQL queries, and returned in WebDAV search results.

This enables web extensions and applications to:

  • Build photo timeline views grouped by capture date
  • Filter photos by camera make/model
  • Display EXIF information (aperture, ISO, focal length, etc.)
  • Show geotagged photos on a map

Changes Summary

File Changes
ocis-pkg/kql/dictionary.peg Added photo keyword to KQL grammar
ocis-pkg/kql/dictionary_gen.go Regenerated parser
services/search/pkg/engine/bleve.go Added explicit field mappings with Store=true for photo fields
services/search/pkg/query/bleve/compiler.go Added photo field mappings to KQL compiler
services/search/pkg/query/bleve/compiler_test.go Added unit tests for photo queries
services/search/pkg/search/service.go Include photo metadata in search results
services/webdav/pkg/service/v0/search.go Added oc:photo-* WebDAV properties

Related Issue

  • This is a new feature enhancement (no existing issue)
  • Related discussion: Photo management is a common use case for personal cloud storage, and exposing EXIF metadata through search enables rich photo gallery experiences similar to Google Photos or Apple Photos.

Motivation and Context

oCIS already extracts and stores photo EXIF metadata via Tika during indexing, but this data was not:

  1. Stored in the Bleve index (fields lacked Store=true)
  2. Exposed through KQL query syntax
  3. Returned in WebDAV search results

This PR addresses all three gaps, enabling photo-centric applications to be built on oCIS.

Use Case Example

I've built a photo gallery web extension ([ocis-photo-addon](https://github.com/paul43210/ocis-photo-addon)) that uses these APIs to:

  • Display photos in a timeline grouped by EXIF capture date
  • Show camera information in a lightbox viewer
  • Link to map locations for geotagged photos

How Has This Been Tested?

Test Environment

  • oCIS 7.3.1+dev (custom build with these changes)
  • Ubuntu 24.04 server
  • Tika 2.x for EXIF extraction
  • ~5,000 indexed photos

Test Cases

1. KQL Date Range Query

curl -u 'user:pass' \
  'https://cloud.example.com/dav/spaces/SPACE_ID' \
  -X REPORT -H "Content-Type: application/xml" \
  -d '<?xml version="1.0"?>
  <oc:search-files xmlns:oc="http://owncloud.org/ns">
    <oc:search>
      <oc:pattern>mediatype:image* AND photo.takenDateTime&gt;=2025-01-01 AND photo.takenDateTime&lt;=2025-12-31</oc:pattern>
      <oc:limit>100</oc:limit>
    </oc:search>
  </oc:search-files>'

2. KQL Camera Filter Query

# Find all photos taken with a Canon camera
<oc:pattern>mediatype:image* AND photo.cameraMake:Canon</oc:pattern>

3. WebDAV Response Verification
Response includes photo properties:

<d:response>
  <d:href>/dav/spaces/.../photo.jpg</d:href>
  <d:propstat>
    <d:prop>
      <oc:photo-taken-date-time>2025-06-15T14:30:00Z</oc:photo-taken-date-time>
      <oc:photo-camera-make>Canon</oc:photo-camera-make>
      <oc:photo-camera-model>EOS R5</oc:photo-camera-model>
      <oc:photo-f-number>2.8</oc:photo-f-number>
      <oc:photo-iso>400</oc:photo-iso>
      <oc:photo-focal-length>85</oc:photo-focal-length>
      <oc:photo-location-latitude>43.6532</oc:photo-location-latitude>
      <oc:photo-location-longitude>-79.3832</oc:photo-location-longitude>
    </d:prop>
  </d:propstat>
</d:response>

4. Unit Tests

go test ./services/search/pkg/query/bleve/... -v

All new tests pass for photo field queries.

Screenshots

N/A - Backend/API changes only. However, the [photo-addon extension](https://github.com/paul43210/ocis-photo-addon) demonstrates the UI possibilities this enables.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Technical debt
  • Tests only (no source changes)

Checklist

  • Code changes
  • Unit tests added
  • Acceptance tests added
  • Documentation ticket raised: (to be created if PR is accepted)

Additional Notes

Key Implementation Detail

The critical fix was adding explicit field mappings with Store=true in bleve.go. Without this, Bleve indexes the fields for searching but doesn't store the values for retrieval:

photoTakenDateTimeMapping := bleve.NewDateTimeFieldMapping()
photoTakenDateTimeMapping.Store = true
photoTakenDateTimeMapping.Name = "Photo.TakenDateTime"

Backward Compatibility

  • No breaking changes to existing APIs
  • Existing searches continue to work unchanged
  • Photo fields are simply additional data in responses
  • Users need to reindex to populate photo metadata in existing indexes

Future Considerations

  • This could be extended to support video metadata
  • Face detection/recognition could use similar patterns
  • Album/collection grouping could build on this foundation

Paul Faure and others added 5 commits January 15, 2026 22:35
This change enables photo gallery applications to access EXIF metadata
through the search API.

Changes:
- Add KQL query support for photo fields:
  - photo.takenDateTime (datetime range queries)
  - photo.cameraMake, photo.cameraModel (keyword queries)
  - photo.fNumber, photo.focalLength, photo.iso (numeric queries)
- Configure Bleve index to store photo fields (Store=true)
- Map photo metadata from Bleve hits to Entity.Photo protobuf
- Add oc:photo-* properties to WebDAV search responses
- Add unit tests for photo field queries

The photo metadata is extracted by Tika during indexing and stored
in the Bleve search index. This enables queries like:
  photo.takenDateTime:[2023-01-01 TO 2023-12-31]
  photo.cameraMake:Canon

Signed-off-by: Paul Faure <[email protected]>
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add location field mappings with Store=true in Bleve index
- Rename properties to oc:photo-location-* for consistency
- Add altitude support alongside latitude/longitude
- Requires index rebuild to take effect
- Add exposure numerator/denominator to search results
- Add altitude extraction from Tika GPS metadata
- All photo EXIF fields now fully exposed via WebDAV search
Copy link
Collaborator

@kobergj kobergj left a comment

Choose a reason for hiding this comment

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

Nice 👍 I love it. Just some question (probably just stupid me) and a super small fix to make the linter happy.

Comment on lines +290 to +292
if field, ok := _photoFields[parts[1]]; ok {
return field
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't quite understand why we need this check. Can't we just return name in this case?

if field, ok := _photoFields[parts[1]]; ok {
return field
}
// Future: case "audio", "image", "location"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Linter complains about file not being properly formatted. I think you need to move this comment above the case statement.

@paul43210
Copy link
Author

paul43210 commented Jan 16, 2026 via email

@sonarqubecloud
Copy link

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants