Skip to main content
The StashEntityStore provides advanced filtering methods that combine local caching with smart field-level population. These methods enable high-performance queries by minimizing network traffic while ensuring data completeness.

Overview

The advanced filtering system builds on the UNSET Pattern and Identity Map to provide:
  • Field-level granularity: Track which fields are loaded vs unqueried
  • Smart population: Automatically fetch only missing fields
  • Local filtering: Query cached data without network calls
  • Fail-fast validation: Ensure required fields are present before filtering

Method Comparison

filter_strict() - Fail-Fast Filtering

Filters cached objects, raising an error if any required fields are missing. Useful when you MUST have complete data.

Signature

Example

When to Use

  • Data validation: Ensure cache is complete before processing
  • Debugging: Identify incomplete cache population
  • Critical operations: Operations that require guaranteed field presence

filter_and_populate() - Smart Hybrid Filtering

The main workhorse method. Filters cached objects, automatically fetching missing fields as needed. Much faster than find() when most data is cached.

Signature

Example

Performance Benefits

Scenario: Cache has 1000 performers with basic info, need to filter by rating100

Batch Size Parameter

Controls how many entities are populated concurrently:

filter_and_populate_with_stats() - Debug Variant

Same as filter_and_populate() but returns detailed statistics. Useful for performance optimization.

Signature

Example

Statistics Dictionary

When to Use

  • Performance analysis: Identify cache inefficiencies
  • Optimization: Determine if cache warming is needed
  • Debugging: Understand why queries are slow

populated_filter_iter() - Lazy Async Iterator

Lazy version of filter_and_populate() that yields results incrementally. Great for large datasets where you want to start processing immediately or can short-circuit early.

Signature

Example: Early Exit

Example: Incremental Processing

Batch Parameters

  • populate_batch: How many to populate concurrently (default: 50)
  • yield_batch: How many to process before yielding (default: 10)

When to Use

  • Large datasets: Process 10,000+ entities incrementally
  • Early exit: Stop processing when you find enough matches
  • Memory efficiency: Don’t load all results into memory
  • Progress reporting: Update UI as results stream in

Real-World Workflow Example

Best Practices

1. Choose the Right Method

2. Cache Warming Strategy

3. Performance Monitoring

4. Field Dependencies

Nested Field Filtering

All advanced filter methods support Django-style nested field specifications using double-underscore (__) syntax. This allows you to filter on properties of related objects without manual joins.

Syntax

  • Simple field: 'rating100', 'favorite'
  • Nested field: 'files__path', 'studio__parent__name'
  • Deep nesting: 'studio__parent__parent__name' (arbitrary depth)
  • Mixed: ['rating100', 'files__path', 'studio__name']

Example: Filter Images by File Properties

Example: Filter by Studio Hierarchy

How It Works

When you specify a nested field like 'files__path', the filter method:
  1. Parses the specification: 'files__path'['files', 'path']
  2. Checks root field: Ensures files relationship is populated
  3. Recursively checks nested fields: Ensures path is populated on each File object
  4. Auto-populates missing data: Fetches only what’s needed from the server

Benefits

  • No manual joins: Express complex queries naturally
  • Selective fetching: Only fetch fields actually needed
  • Type-safe: Compile-time checking with IDE autocomplete
  • Efficient: Uses identity map to avoid duplicate fetches

Nested Field Examples

With filter_strict()

Performance Tip

Nested field filtering is most efficient when:
  1. Root relationships are already cached
  2. Only leaf fields need population
  3. Batch sizes are tuned for your dataset

Integration with UNSET Pattern

The advanced filter methods work seamlessly with the UNSET Pattern:

Preloading Files with find_iter(BaseFile, ...)

find_iter(BaseFile, ...) bulk-loads files and warms the identity map. Each file is deserialized as its concrete polymorphic subtype (VideoFile, ImageFile, GalleryFile, or the fieldless BasicFile) based on its __typename. On servers that expose the file reverse-relationship resolvers (stashapp/stash #6938), the reverse relationships (scenes, images, galleries) are populated in the same query; on older servers they are left UNSET (there is no per-file fallback in the bulk path — use populate() on an individual file for the path-filter fallback).

Supported FileFilterType filters

Django-style kwargs translate directly for the scalar FileFilterType fields:

Known limitation: list-membership and complex file filters

The kwargs shorthand does not auto-translate every FileFilterType field. These must be passed as raw filter dicts (matching the GraphQL input shape), and list-membership values must be given as explicit lists:
  • zip_file (MultiCriterionInput) and parent_folder (HierarchicalMultiCriterionInput) — the shorthand will not wrap a single value into a list; pass {"value": [ids], "modifier": "INCLUDES"}.
  • hashes ([FingerprintFilterInput!]) and duplicated (FileDuplicationCriterionInput) — no shorthand; pass the raw dict.

See Also