# Multi-Index Federation and Cross-Search **Last updated:** 2026-04 | Verified: MCP 2026-04 **Status:** GA (single-index), Not supported (native cross-index) **Category:** RAG Architecture & Semantic Search --- ## Introduksjon Et av de vanligste spørsmålene fra enterprise-arkitekter er: "Kan vi søke på tvers av flere Azure AI Search-indekser i en enkelt spørring?" Svaret er **nei** — Azure AI Search støtter ikke native multi-index federation. Hvert søk er alltid avgrenset til én enkelt indeks. Dette er en bevisst designbeslutning, ikke en begrensning. Enkelt-indeks-søk gir konsistente scorer, unified ranking, og forutsigbar ytelse. Cross-index-søk ville kreve score-normalisering, resultat-merging, og distribuert ranking — noe som introduserer betydelig kompleksitet og uforutsigbarhet. For scenarioer der data logisk tilhører separate indekser (ulike skjemaer, compliance-krav, eller ulike formål), må applikasjonslaget implementere orkestrering. Denne filen beskriver arkitekturmønstre, routing-strategier og best practices for slike scenarioer. **Viktig funn:** Microsofts offisielle FAQ sier eksplisitt: *"Can I search across multiple indexes? No. A query is always scoped to a single index."* **Multi-region støtte:** Azure AI Search er en single-region service, men du kan oppnå høyere reliability ved å deploye identiske search services i flere regioner. Data synkroniseres via push eller pull (indexer) APIer. Load balancing håndteres av Azure Front Door, Traffic Manager, eller Application Gateway. Data residency: innhold lagres i regionen du velger, uten kryssregional dataflyt uten eksplisitt autorisasjon. **Multi-vector fields (Preview):** Azure AI Search støtter nå multiple vektorer i ett dokumentfelt via `Collection(Edm.ComplexType)` — opp til 100 vektorer per dokument. Nyttig for multimodal data og lange dokumenter. `perDocumentVectorLimit`-parameteren kontrollerer antall matchende vektorer per dokument i query-resultater. ## Kjernekomponenter ### Hvorfor Azure AI Search ikke støtter cross-index queries | Utfordring | Forklaring | |-----------|------------| | **Scoring-isolasjon** | BM25-scores er relative til dokumentfrekvens *innenfor* indeksen — scorer fra ulike indekser kan ikke sammenlignes direkte | | **Skjema-forskjeller** | Ulike indekser kan ha helt ulike felt, datatyper og analysatorer | | **Ingen unified ranking** | Ingen innebygd mekanisme for å re-ranke resultater på tvers av indekser | | **Ingen distribuerte transaksjoner** | Oppdateringer til flere indekser er ikke atomiske | ### Enkelt-indeks vs. multi-indeks | Aspekt | Enkelt indeks | Multiple indekser | |--------|--------------|-------------------| | Query-logikk | Enkel, unified | Kompleks, krever orkestrering | | Scoring | Konsistent | Inkonsistent mellom indekser | | Vedlikehold | Enklere | Mer komplekst | | Filtrering | Native, effektiv | Per-indeks, applikasjons-merging | | Sikkerhet | Dokumentnivå-filtrering | Indeks-nivå isolasjon | | Skalerbarhet | Vertikal (større tier) | Horisontal (flere services) | ### Nyere relevante features (2025) | Feature | Status | Relevans | |---------|--------|----------| | Multi-vector field support | GA (2025) | Lagre multiple vektorer per dokument i én indeks | | Agentic Retrieval | Preview | LLM-assistert query planning, men fremdeles single-index | | Targeted vector filters | Preview | Filtre spesifikt for vektor-subqueries | ## Arkitekturmønstre ### Mønster 1: Enkelt indeks med filtrering (anbefalt) **Flyt:** Data fra multiple kilder → Felles indeks med type/kilde-felt → Filtrering ved søk ```python # Alle dokumenttyper i én indeks med type-felt results = client.search( search_text="anskaffelsesregler", filter="doc_type eq 'regelverk' and department eq 'HR'", select=["title", "content", "doc_type", "department"], top=10 ) ``` **Fordeler:** - Enklest implementering - Unified scoring og ranking - Native filtrering, facettering - Ingen orkestreringskode nødvendig **Ulemper:** - Skjemaet må være tilstrekkelig fleksibelt for alle dokumenttyper - Indeksen kan bli stor (skalering vertikalt) - Alle dokumenter deler analysatorer og innstillinger **Beste for:** De fleste enterprise-scenarioer der data har lignende struktur. ### Mønster 2: Parallell query med applikasjons-merging **Flyt:** Query → Fork til N indekser (parallelt) → Samle resultater → Score-normalisering → Merged resultat ```python from azure.search.documents import SearchClient from azure.identity import DefaultAzureCredential import asyncio async def query_multiple_indexes(query_text, indexes): credential = DefaultAzureCredential() async def query_index(index_name): client = SearchClient( endpoint=endpoint, index_name=index_name, credential=credential ) results = [] async for result in client.search(search_text=query_text, top=10): results.append({ "source_index": index_name, "score": result["@search.score"], **result }) return results # Parallelle queries tasks = [query_index(idx) for idx in indexes] all_results = await asyncio.gather(*tasks) # Flatten og normaliser merged = [] for results in all_results: merged.extend(results) # MERK: Score-normalisering nødvendig her merged = normalize_scores(merged) merged.sort(key=lambda x: x["normalized_score"], reverse=True) return merged[:10] def normalize_scores(results): """Min-max normalisering per indeks.""" by_index = {} for r in results: idx = r["source_index"] if idx not in by_index: by_index[idx] = [] by_index[idx].append(r) for idx, items in by_index.items(): scores = [i["score"] for i in items] min_s, max_s = min(scores), max(scores) range_s = max_s - min_s if max_s != min_s else 1 for item in items: item["normalized_score"] = (item["score"] - min_s) / range_s return results ``` **Fordeler:** - Støtter fundamentalt ulike skjemaer - Compliance-isolasjon mellom indekser - Horisontal skalering **Ulemper:** - Score-normalisering er heuristisk, ikke eksakt - Økt latency (selv med parallellisering) - Kompleks kode å vedlikeholde - Resultater kan "konkurrere" unfairly mellom indekser **Beste for:** Scenarioer med fundamentalt ulike datatyper (HR-håndbok vs. produktkatalog). ### Mønster 3: Query routing basert på intent **Flyt:** Query → Intent-analyse (LLM/classifier) → Route til riktig indeks → Enkelt-indeks søk → Resultat ```python def route_query(query_text): """Bestem hvilken indeks som er mest relevant.""" # Enkel keyword-basert routing if any(word in query_text.lower() for word in ["anskaffelse", "kontrakt", "anbud"]): return "regelverk-index" elif any(word in query_text.lower() for word in ["personal", "ferie", "lønn"]): return "hr-index" else: return "general-index" # Eller med LLM-basert intent-klassifisering def route_query_llm(query_text): response = openai_client.chat.completions.create( model="gpt-4o-mini", messages=[{ "role": "system", "content": "Classify the query into one of: regelverk, hr, general" }, { "role": "user", "content": query_text }] ) intent = response.choices[0].message.content.strip() return f"{intent}-index" ``` **Fordeler:** - Kun én indeks queries per request (lavest latency) - Tydelig domene-separasjon - Skalerbar routing-logikk **Ulemper:** - Routing-feil betyr at brukeren ikke finner det de leter etter - LLM-basert routing legger til latency og kostnad - Krever vedlikehold av routing-logikk **Beste for:** Klart adskilte domener med liten overlapp. ### Mønster 4: Multi-region search services **Flyt:** Query → Nearest region service (via Traffic Manager) → Lokalt søk → Resultat For geo-distribuerte brukere der latency er kritisk: - Identiske indekser i flere regioner - Synkronisering via push/pull API - Azure Traffic Manager, Front Door, eller Application Gateway for routing **Beste for:** Globale applikasjoner med latency-krav. ## Beslutningsveiledning ### Valg av indeks-topologi ``` Trenger du ulike skjemaer per datakilde? ├── Nei → Enkelt indeks med filtrering (Mønster 1) └── Ja → Er datakildene compliance-adskilt? ├── Ja → Multi-indeks med routing (Mønster 3) └── Nei → Kan skjemaene generaliseres? ├── Ja → Enkelt indeks med complex types └── Nei → Multi-indeks med parallell query (Mønster 2) ``` ### Vanlige feil 1. **Opprette separate indekser for hvert datasett** — Start med filtrering i én indeks 2. **Sammenligne BM25-scores direkte mellom indekser** — Scores er relative, ikke absolutte 3. **Sekvensiell querying av multiple indekser** — Bruk alltid parallell utførelse 4. **Implementere cross-index joins** — Azure AI Search støtter ikke dette 5. **Ignorere skjema-denormalisering** — Dupliser data hvis nødvendig for søkbarhet ### Røde flagg - Behov for mer enn 3-4 indekser → Vurder om indeksdesignet er suboptimalt - Brukere klager over manglende resultater → Mulig routing-feil i multi-indeks-oppsett - Inkonsistente scorer mellom søk → Score-normalisering trenger kalibrering ## Integrasjon med Microsoft-stakken | Tjeneste | Rolle | |----------|-------| | **Azure Traffic Manager** | Geo-basert routing mellom search services | | **Azure Front Door** | Lastbalansering og CDN for multi-region | | **Azure Application Gateway** | L7 load balancing for search requests | | **Azure API Management** | API-gateway med routing-logikk for multi-indeks | | **Semantic Kernel** | Orchestration-framework for multi-indeks RAG | ## Offentlig sektor (Norge) ### Data-klassifisering og indeks-separasjon - **Ugradert data:** Kan samles i én indeks med filtrering - **Fortrolig/begrenset:** Bør ha egen indeks med strengere tilgangskontroll - **Sikkerhetsgradert:** Kan kreve egen search service i isolert nettverk ### Compliance-krav - **Arkivloven:** Dokumenter fra ulike arkivserier kan kreve logisk separasjon - **Forvaltningsloven:** Tilgangskontroll per sak/avdeling - **GDPR:** Persondata kan kreve egen indeks for enklere sletting (right to be forgotten) ### Anbefalt tilnærming For de fleste offentlige virksomheter: 1. **Primærindeks:** All ugradert dokumentasjon i én indeks med avdelings-/kategori-filtrering 2. **Sekundærindeks:** Persondata eller begrenset informasjon med RBAC 3. **Routing:** Intent-basert routing for å bestemme hvilken indeks som søkes ## Kostnad og lisensiering ### Kostnadsimplikasjoner av multi-indeks | Topologi | Kostnadsfaktorer | |----------|-----------------| | Enkelt indeks | Én search service, standard lagring og query-kostnad | | Multiple indekser (én service) | Delte ressurser, men økt lagring | | Multiple search services | Separate kostnader per service, duplikert lagring | | Multi-region | Multiplisert lagring + synkroniseringskostnad | ### Kostnadsoptimering - **Start med enkelt indeks** — Unngå unødvendig kompleksitet og kostnad - **Bruk replika-fordeling** fremfor separate services der mulig - **Vurder search service tier** basert på samlet indeksstørrelse og query-volum - **Synkroniser incrementally** i multi-region — ikke full re-indeksering ## For arkitekten (Cosmo) ### Spørsmål å stille kunden 1. Hvor mange datakikylder har dere, og har de lignende eller ulik struktur? 2. Er det compliance-krav som krever fysisk separasjon av data? 3. Trenger brukerne å søke på tvers av alle datakilder, eller er domenene adskilte? 4. Hva er latency-kravene — kan parallell multi-indeks query aksepteres? 5. Har dere geo-distribuerte brukere som trenger multi-region? 6. Hva er budsjett — én stor service vs. flere mindre? ### Fallgruver - Å designe for cross-index fra start uten å vurdere filtrering i enkelt indeks - Å underestimere kompleksiteten i score-normalisering og resultat-merging - Å anta at fremtidige Azure-oppdateringer vil løse cross-index — dette er et bevisst designvalg - Å bruke LLM for query routing uten fallback til bredere søk ### Anbefalinger per modenhetsnivå | Nivå | Anbefaling | |------|------------| | **Starter** | Enkelt indeks med filtrering — alltid start her | | **Intermediær** | Legg til separate indekser kun ved compliance-krav, med intent-routing | | **Avansert** | Multi-region med synkronisering, custom orkestrering, semantic reranking av merged resultater | ### Viktig designprinsipp > **Default til enkelt indeks med filtrering.** Opprett separate indekser kun når du har en konkret, dokumentert grunn — ikke "for sikkerhets skyld." Grunner som rettferdiggjør separate indekser: - Fundamentalt ulikt skjema (tekst vs. strukturert data) - Compliance-krav til fysisk separasjon - Ulik livsyklus (hyppig vs. sjelden oppdatering) - Ulike tilgangsmodeller (intern vs. ekstern) ## Kilder og verifisering ### Verified (MCP-research) - [Azure AI Search FAQ — Cross-index queries](https://learn.microsoft.com/en-us/azure/search/search-faq-frequently-asked-questions) - [Multi-region deployments](https://learn.microsoft.com/en-us/azure/search/search-multi-region) - [Grounding data design — Index topology](https://learn.microsoft.com/en-us/azure/well-architected/ai/grounding-data-design) - [Multi-vector field support](https://learn.microsoft.com/en-us/azure/search/vector-search-multi-vector-fields) - [Tutorial: Index from multiple data sources](https://learn.microsoft.com/en-us/azure/search/tutorial-multiple-data-sources) - [GitHub: Multiple search services (.NET)](https://github.com/Azure-Samples/azure-search-dotnet-scale/tree/main/multiple-search-services) ### Baseline (modellkunnskap) - Score-normaliserings-kode - Routing-eksempler - Offentlig sektor-anbefalinger