Skip to content

[FEATURE] Add search_pipeline support to _msearch via MultisearchBody #2061

Description

@gndcshv

Is your feature request related to a problem?

The OpenSearch server accepts a per-sub-request search_pipeline on _msearch — placed as a top-level field in the search source body — but the opensearch-java client provides no way to set it.

org.opensearch.client.opensearch.core.msearch.MultisearchBody has no pipeline / search_pipeline field, so applications that want to route individual msearch sub-requests through different search pipelines currently have to bypass the typed builder and construct raw NDJSON by hand.

Concrete use case. A hybrid-search workload where each sub-request needs its own normalization pipeline:

GET /_msearch
{"index":"bulk-search-test"}
{"size":3,"query":{"hybrid":{"queries":[{"match":{"title":"running shoes"}},{"knn":{"embedding":{"vector":[0.85,0.15,0.05],"k":5}}}]}},"search_pipeline":"nlp-pipeline-a"}
{"index":"bulk-search-test"}
{"size":3,"query":{"hybrid":{"queries":[{"match":{"title":"speaker"}},{"knn":{"embedding":{"vector":[0.05,0.15,0.9],"k":5}}}]}},"search_pipeline":"nlp-pipeline-b"}
{"index":"bulk-search-test"}
{"size":3,"query":{"term":{"category":"footwear"}}}

This request works end-to-end when sent as raw NDJSON via against a 3.7 cluster, but there is no way to express it through MsearchRequest.Builder today — MultisearchBody.Builder has no searchPipeline(...) method.

What solution would you like?

Add a searchPipeline field to MultisearchBody (JSON key search_pipeline), matching the accessor name used by SearchRequest#searchPipeline for single _search. This lets callers write:

MsearchRequest req = MsearchRequest.of(m -> m
    .searches(s -> s
        .header(h -> h.index("bulk-search-test"))
        .body(b -> b
            .query(/* ... */)
            .searchPipeline("nlp-pipeline-a")   // NEW
        )
    )
    .searches(s -> s
        .header(h -> h.index("bulk-search-test"))
        .body(b -> b
            .query(/* ... */)
            .searchPipeline("nlp-pipeline-b")   // NEW
        )
    )
);

The emitted NDJSON should match the working payload above (each search_pipeline on its body line, not the header line).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions