RAG on managed Apache Solr — one pip install
Opensolr is now a native LangChain vector store. Server-side GPU embeddings, hybrid BM25 + kNN search, and a managed Solr 9 index behind every retriever — with zero embedding models to configure.
The whole tutorial
This is not a teaser — this is the entire integration. No embedding model, no API key juggling, no schema design.
from langchain_opensolr import OpensolrVectorStore vs = OpensolrVectorStore( index="mysite__dense", # vector-enabled Opensolr index email="you@example.com", api_key="YOUR_OPENSOLR_API_KEY", create_if_missing=True, # provisions the index on first use ) vs.add_texts(["Hybrid search fuses BM25 with vector similarity", "Cats sleep sixteen hours a day"]) docs = vs.similarity_search("how do lexical and semantic search combine?")
No embedding model was configured, because embedding happens server-side — on Opensolr's GPU infrastructure, at both index and query time.
Try it without an account
A public demo account, so the quickstart above runs before you decide anything.
export OPENSOLR_EMAIL=mcp@opensolr.com export OPENSOLR_API_KEY=420b8b23e7b12dc8ab838932145a5065
The index mcp_demo_d1__dense is already loaded with 300 news articles, so search, filtering and grounded answers work the moment you connect. You also get the write path: create your own index on the account, ingest into it and query it. Deletion is not available on this shared key — no index here can be deleted or reconfigured by hand. Whatever you create is removed automatically after 3 days.
- Anything you create there is deleted after 3 days. Automatically, without warning or export — indexes you created included.
- The account is shared with everyone reading this page. Your index is visible to them and they can add documents to it, as you can to theirs. Nobody can delete or reconfigure an index here — that is switched off for this key — but never put anything real, private or client-owned in it.
- The limits are per index, and deliberately small. 200 MB of bandwidth and 50 MB of disk per index. Bandwidth is the one you will hit first: it covers a demo, a tutorial and a proof of concept, and it will not carry an application.
When you want an index that is private, yours and still there next week, get your own key — free 15-day trial, no card — and change the two variables above. Nothing else in your code changes.
What happens under the hood
Your app talks to one package. The package talks to a managed pipeline that already exists.
Why this is different
Most vector stores in the LangChain directory make you bring your own embedding model and run your own database. This one doesn't.
Zero embedding config
The shortest constructor in the directory: api_key + index. Texts and queries are embedded server-side on GPU — no OpenAI key, no local model, no sentence-transformers install.
True hybrid search
Pure vector search fails on exact identifiers; pure BM25 fails on meaning. hybrid=True fuses both scores per document, with four modes and a tunable alpha balance.
Lossless metadata + filters
Metadata round-trips exactly as you stored it, and filters work both ways: filter={"category": "docs"} or any raw Solr fq expression when you need real power.
Auto index provisioning
create_if_missing=True provisions a vector-enabled Solr 9 index on first use — pick us, de or fi. No servers, no schema files, no ZooKeeper.
Drops into any chain
vs.as_retriever() and it's a standard LangChain retriever — RAG tutorials, agents, LangGraph, LCEL pipelines. Everything that accepts a retriever accepts this.
Plain Apache Solr underneath
Every index is also a real Solr core with the native /select API — facets, highlighting, spellcheck, stats. When you outgrow the vector-store interface, nothing is locked away.
Two lines you'll actually use
Hybrid retrieval with metadata filters, and the retriever that plugs into every RAG example ever written.
Hybrid search, filtered
docs = vs.similarity_search(
"affordable restaurants",
k=5,
hybrid=True, # BM25 + kNN, fused
mode="union", # or keywords_required,
# meaning_required,
# intersection
alpha=0.5, # semantic ↔ lexical
filter={"city": "Cluj"},
)As a retriever, in any chain
retriever = vs.as_retriever(
search_kwargs={"k": 5, "hybrid": True}
)
# now use it anywhere LangChain
# expects a retriever:
chain = (
{"context": retriever, "question": ...}
| prompt | llm
)Your Search Tuning follows you
Relevance is configured once, in your Control Panel — not re-implemented in every codebase.
- Saved per index: everything you set in Index Settings → Search Tuning (semantic↔lexical balance, field weights, minimum match, search mode, vector candidate pool, content quality boost) is stored with your index.
- Applies automatically here: every search and every RAG answer from this integration runs through the same tuned pipeline as your hosted search page — change a slider in the Control Panel and the very next query uses it. No redeploy, no code change.
- Overridable per call:
tuning={"search_mode": "keywords_required", "fw_title": 0.2, "mm": "strict"}beats the saved settings for that one request. Defaults match the platform exactly when you send nothing. - Fresh Results Bias: pass
fresh_biasto rank newer documents higher — scores are multiplied by a recency curve oncreation_date. It re-orders and never filters: the hit count is unchanged and undated documents keep their place. This is the same control visitors get as the Fresh toggle on the hosted search page. Not to be confused withfreshness_boost, which is a hard date window in days and does remove results.
Tested on our own production index
Every release runs a live end-to-end suite against real Opensolr infrastructure — no mocks.
- Full write path through the async Data Ingestion queue: queued → server-side embeddings & enrichment → searchable, with metadata and id round-trips verified. Metadata lands in typed Solr fields; the suffixes and what they enable are in the Vector Search Schema Reference.
- Real-corpus retrieval against a replica of opensolr.com's own search index: pure-semantic hits with zero keyword overlap („how do I get my data back after a disaster” → backup docs), cross-lingual queries (Romanian → English content), all hybrid modes and the full alpha range.
- PDF ingestion via
rtf:true: server-side text extraction and content-type detection, then semantic retrieval from the extracted content. - Grounded RAG answers: one call runs hybrid retrieval and feeds the top hits to the LLM (configurable docs/words, custom instruction) — verified with a question answerable only from the ingested PDF.
Build your first RAG pipeline tonight
Free 15-day trial, no credit card. The included AI quota comfortably covers the whole tutorial — index, embed, search, and retrieve.
Need a vector-enabled environment in another region? We deploy them on request — dedicated, in the region you choose (paid add-on).