opensearch-project / opensearch-project/opensearch-java

[FEATURE] Add `search_pipeline` support to `_msearch` via `MultisearchBody`

Open Beginner friendly
#2,061 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement untriaged
Dominant language
Java
Stars
165
Forks
250
Avg merge
1d 18h
Merged PRs (30d)
26

Description

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).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with org.opensearch.client.opensearch.core.msearch.MultisearchBody and its Builder, comparing the requested accessor with SearchRequest#searchPipeline. Verify the MsearchRequest builder emits search_pipeline on each sub-request body line rather than the header line, using the NDJSON example as the completion check.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api
Issue type
Feature
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
75/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.