Matching Plugin

The Luna-Vinder matching plugin integrates into the Python Matcher Proxy plugin system, enabling intelligent routing of search requests to Luna-Vinder services. The plugin analyzes incoming requests, determines compatibility with available projections and indexes, and routes requests to appropriate Matcher instances.

Integration & Configuration

To integrate Luna-Vinder into the `Python Matcher Proxy plug-in system`_, follow the steps below:

Manual Installation

If you’re running Python Matcher Proxy outside of Docker, manually copy the Luna-Vinder plugin:

cp -r $LVSM_ROOT/libs/vinder-client/vinder_client/. \
    $LUNA_PYTHON_MATCHER_ROOT/luna_python_matcher/plugins/vinder_plugin

Note

Skip this step if Python Matcher Proxy is running in Docker. The vinder search module plugin is integrated by default when running in a container.

Plugin Configuration

Configure the plugin settings in Luna Configurator. The plugin requires connection information for Projector and Matcher services:

LUNA_VINDER_PLUGIN = {
    "PROJECTOR": {
        "origin": "http://127.0.0.1:5260",
        "api": 1
    },
    "MATCHERS": [
        {"origin": "http://127.0.0.1:5270", "api": 1},
        {"origin": "http://127.0.0.1:5271", "api": 1}
    ],
    "TIMEOUT": 1
}

Configuration parameters:

  • PROJECTOR - connection settings for Projector service

    • origin - base URL of the Projector service

    • api - API version to use

  • MATCHERS - list of available Matcher instances

    • origin - base URL of each Matcher service

    • api - API version to use

  • TIMEOUT - request timeout in seconds

Activating the Plugin

Enable the plugin by adding it to the active plugins list in Luna Configurator:

LUNA_MATCHER_PROXY_ACTIVE_PLUGINS = ["vinder_plugin"]

Important

The plugin name must match the directory name you specified during installation (step 1).

Warning

Plugin settings are not Python Matcher Proxy settings. Changing them does not automatically restart Python Matcher Proxy. After modifying plugin configuration, you must manually restart Python Matcher Proxy to apply the new settings.

How the Plugin Works

The Luna-Vinder plugin acts as an intelligent request analyzer and router. When a matching request arrives at Python Matcher Proxy, the plugin performs the following steps:

Request Analysis

The plugin examines each incoming request to determine if it can be processed by Luna-Vinder. It checks:

  1. Candidate Data Source The data source (origin) specified in the request must match a projection’s origin.

  2. Descriptor Compatibility The descriptor version and type must be present in at least one loaded index.

  3. Filter Compatibility Request filters must be a subset of conditions that can be satisfied by an index’s composite fields.

Selection Criteria

For a request to be routed to Luna-Vinder, the following conditions must be met:

  • Projection Match: At least one projection exists with a matching origin and compatible filters

  • Index Availability: An index must exist on the selected projection with composite fields covering all request filters

  • Target Availability: All attributes used in filters must be present in the projection’s targets

Note

If candidate filters are not fully covered by index conditions, matching will not be performed via Luna-Vinder.

Request Routing Examples

Consider the following projections and index configurations:

Projections Setup

[
    {
        "projection_id": "e58a8336-c412-4aa2-935c-92ad8a6ebd4e",
        "origin": "events",
        "params": {
            "projection_type": "view",
            "targets": ["event_id", "handler_id", "age", "gender"],
            "filters": {
                "age__gte": 50
            }
        },
        "description": "Events with age >= 50"
    },
    {
        "projection_id": "4172028d-c536-4186-81fb-f6cd8d9e5d19",
        "origin": "events",
        "params": {
            "projection_type": "view",
            "targets": ["event_id", "handler_id", "age", "gender"],
            "filters": {
                "age__gte": 30
            }
        },
        "description": "Events with age >= 30"
    },
    {
        "projection_id": "1371b925-322f-4993-bff5-aa102de89229",
        "origin": "events",
        "params": {
            "projection_type": "view",
            "targets": ["event_id", "handler_id", "age", "gender"],
            "filters": {}
        },
        "description": "All events"
    }
]

Index Configuration

[
    # index_1: allows filtering by age on projection with age >= 50
    {
        "projection_id": "e58a8336-c412-4aa2-935c-92ad8a6ebd4e",
        "index_composite_fields": ["age"]
    },

    # index_2: allows filtering by age and gender on projection with age >= 30
    {
        "projection_id": "4172028d-c536-4186-81fb-f6cd8d9e5d19",
        "index_composite_fields": ["age", "gender"]
    },

    # index_3: no filtering fields, searches all events in projection
    {
        "projection_id": "1371b925-322f-4993-bff5-aa102de89229",
        "index_composite_fields": []
    }
]

Example Requests

Example 1: Success - No additional filters

{
    "references": [...],
    "candidates": [
        {
            "filters": {
                "origin": "events"
            },
            "targets": ["event_id", "age", "gender", "similarity"]
        }
    ]
}

Result: ✅ Projection 1371b925-322f-4993-bff5-aa102de89229 selected with index_3. Searches across all events without additional filtering.

Example 2: Failed - Unsupported filter

{
    "references": [...],
    "candidates": [
        {
            "filters": {
                "origin": "events",
                "cities": ["Moscow"]
            },
            "targets": ["event_id", "age", "gender", "similarity"]
        }
    ]
}

Result: ❌ Projection 1371b925-322f-4993-bff5-aa102de89229 could be selected, but no index exists that allows filtering by cities. The request cannot be processed by Luna-Vinder.

Example 3: Success - Age filter

{
    "references": [...],
    "candidates": [
        {
            "filters": {
                "origin": "events",
                "age__gte": 50
            },
            "targets": ["event_id", "age", "gender", "similarity"]
        }
    ]
}

Result: ✅ Either projection e58a8336-c412-4aa2-935c-92ad8a6ebd4e with index_1 or projection 4172028d-c536-4186-81fb-f6cd8d9e5d19 with index_2 will be selected. Both can satisfy the age filter.

Example 4: Success - Age and gender filters

{
    "references": [...],
    "candidates": [
        {
            "filters": {
                "origin": "events",
                "age__gte": 60,
                "gender": 0
            },
            "targets": ["event_id", "age", "gender", "similarity"]
        }
    ]
}

Result: ✅ Projection 4172028d-c536-4186-81fb-f6cd8d9e5d19 selected with index_2. This is the only index that supports both age and gender filtering, and the projection includes events with age >= 30, which covers age >= 60.

Example 5: Failed - Missing index fields

{
    "references": [...],
    "candidates": [
        {
            "filters": {
                "origin": "events",
                "age__gte": 20,
                "gender": 0
            },
            "targets": ["event_id", "age", "gender", "similarity"]
        }
    ]
}

Result: ❌ Projection 1371b925-322f-4993-bff5-aa102de89229 matches the origin and includes all events, but index_3 has no composite fields for filtering by age or gender. The request cannot be processed.

Filter Requirements

Important

For candidate filters to work correctly:

  • Targets: The attributes used in filters must be present in the projection’s targets

  • Index Fields: The attributes must be present in the index’s composite_fields (unless the filters exactly match the projection’s filters)

  • Projection Filters: Request filters must be compatible with (more restrictive than or equal to) the projection’s filters

Result Processing

After successful matching, the plugin:

  1. Executes Search: Routes the request to the selected Matcher

  2. Applies Thresholds: Filters results based on similarity thresholds

  3. Applies Limits: Respects the requested result limit

  4. Enriches Results: Adds additional metadata to the response

  5. Returns Response: Sends enriched results back to Python Matcher Proxy in standard format

The enriched response maintains compatibility with the Luna API, allowing seamless integration with existing clients.

Fallback Behavior

If the plugin determines that a request cannot be processed by Luna-Vinder:

  • The request is not forwarded to Matcher services

  • Python Matcher Proxy can fall back to standard matching mechanisms (if configured)

  • An appropriate error response is returned if no fallback is available

Tip

Monitor plugin logs to understand why requests are not being routed to Luna-Vinder. This information helps optimize projection and index configurations.

Best Practices

Design Projections for Common Queries

Create projections that match your most frequent search patterns to maximize Luna-Vinder usage.

Index Composite Fields Wisely

Include only the fields you need to filter by. Follow cardinality rules: order fields from lowest to highest cardinality.

Use Appropriate Projection Filters

Pre-filter data at the projection level to reduce data volume and improve search performance.

Test Filter Combinations

Verify that your expected filter combinations are supported by your projection and index configuration.