Skip to main content
Sometimes the answer is spread across separate corpora - a product catalog, its reviews, and an FAQ - that you keep as distinct indexes. Multi-index search queries several loaded indexes in a single call and returns the global top-K, with each result tagged by its source index. See query_multi_index in the reference.

Usage

Load the indexes (in bulk with load_indexes), then query them together with query_multi_index. Every result document carries an index_name so you know where it came from.
import asyncio
from moss import MossClient, QueryOptions

async def main():
    client = MossClient(MOSS_PROJECT_ID, MOSS_PROJECT_KEY)
    indexes = ["products", "reviews", "faqs"]

    # Bulk-load (best-effort; one failure does not roll back the others).
    result = await client.load_indexes(indexes)
    print(f"loaded={result.loaded} failed={result.failed}")

    # One query across all three; global top-K, tagged by source.
    results = await client.query_multi_index(
        indexes, "wireless headphones battery life", QueryOptions(top_k=6)
    )
    for doc in results.docs:
        print(f"[{doc.index_name}] {doc.id} score={doc.score:.3f} {doc.text[:60]}")

    await client.unload_indexes(indexes)

asyncio.run(main())

Behavior notes

  • All indexes must be loaded locally (via load_index or load_indexes) and share the same embedding model.
  • top_k is global, not per-index - it caps the merged result set.
  • Multi-index search is embedding-only: QueryOptions.alpha is ignored (forced to 1.0), because BM25 scoring across separate corpora is unsound (IDF is per-corpus). filter and embedding work the same as in single-index query.

Bulk lifecycle

load_indexes(names) returns a LoadIndexesResult with loaded and failed. It is best-effort: a typo in one name does not roll back the others, and reloading an already-loaded index is idempotent. unload_indexes(names) releases them when you are done.
# A typo on one name does not stop the others from loading.
partial = await client.load_indexes(["products", "does-not-exist-xyz"])
print(partial.loaded, partial.failed)

Hybrid search

Single-index alpha blending (multi-index is embedding-only).

MossClient reference

query_multi_index, load_indexes, unload_indexes.