AI-API - Hybrid Search (embed_and_search)

AI API: Vectors, Images & LLM
AI API

Hybrid Search (embed_and_search)

One call does what the hosted search page does: the query is cleaned and embedded with the e5 model, then run against your index as a hybrid keyword + vector query using the field weights, boosts and freshness settings saved under Search Tuning for that index. You get back ranked documents with highlighting, facets, spellcheck and the query embedding itself. This is the retrieval step used by langchain-opensolr, llama-index-opensolr, opensolr-haystack, the MCP server and the Laravel Scout driver.

Endpoint

GET or POST https://api.opensolr.com/solr_manager/api/embed_and_search
AI host. Like every AI endpoint this one lives on api.opensolr.com, not on opensolr.com. It works on indexes that hold vector embeddings (Web Crawler, Data Ingestion, or the CMS integrations) and counts as one request against your monthly AI cap.

Parameters

ParameterStatusDescription
emailRequiredYour Opensolr registration email address
api_keyRequiredYour Opensolr API key (master key, or a scoped key that allows this endpoint)
index_nameRequiredThe index to search
qRequiredThe user query, plain text
rows / startOptionalPage size and offset (default 10 / 0)
inOptionalContent scope: web (crawled HTML pages), media (documents/files), or all. Use all for indexes filled by the Data Ingestion API
freshOptionalyes to boost recent documents, no for pure relevance (default follows your Search Tuning)
clean_qOptionalProvide your own cleaned/stop-worded query and skip the server-side cleaning
fw_title, fw_description, fw_text, fw_uriOptionalPer-request field weights, overriding the saved Search Tuning
lexical_weight, vector_weight, vector_topk, search_mode, mm, quality_boost, min_scoreOptionalHybrid tuning overrides — same knobs as the Search Tuning tab; omit to use the index defaults

How It Works

  1. The query is normalised (stop words, accents, punctuation) unless you pass clean_q.
  2. It is embedded into a 1024-dimension vector with the same model that embedded your documents.
  3. Solr receives a hybrid request: BM25 keyword matching over the weighted fields plus a k-nearest-neighbour vector match, fused with your saved lexical/vector weights, boosts, freshness and quality settings.
  4. The response is assembled with highlights, facets and spellcheck exactly as the hosted search page renders them.

Because the index’s own tuning is applied server-side, an application using this endpoint returns the same results as the Opensolr search UI for that index — no query DSL to maintain. When you need raw Solr control instead, query the index directly (parameters explained) and embed with embed.

Response

KeyTypeDescription
statusbooltrue on success; errors come as {"status":false,"msg":"ERROR_..."}
results.docsarrayRanked documents with all stored fields (id, uri, title, description, text, meta_*, …)
results.numintTotal matches
results.hlobjectHighlight snippets per document id
results.facets / facet_pivot / statsobjectFacet counts as configured for the index
results.spellcheckobjectDid-you-mean suggestions
results.qtime / params / debugmixedSolr timing, the effective parameters and debug info
embeddingsstringJSON-encoded 1024-float vector of the query — reuse it for your own KNN queries

Code Examples

$_ cURL

curl -s -G "https://api.opensolr.com/solr_manager/api/embed_and_search" \
  --data-urlencode "email=YOUR_EMAIL" --data-urlencode "api_key=YOUR_API_KEY" \
  --data-urlencode "index_name=my_index" --data-urlencode "q=how do I reset my password" \
  --data-urlencode "rows=5" --data-urlencode "in=all" --data-urlencode "fresh=no"

PHP PHP

$q = http_build_query(['email' => 'YOUR_EMAIL', 'api_key' => 'YOUR_API_KEY', 'index_name' => 'my_index',
    'q' => 'how do I reset my password', 'rows' => 5, 'in' => 'all', 'fresh' => 'no']);
$r = json_decode(file_get_contents("https://api.opensolr.com/solr_manager/api/embed_and_search?{$q}"), true);
foreach ($r['results']['docs'] as $doc) {
    echo $doc['title'], ' — ', $doc['uri'], "\n";
}

Py Python

import requests

r = requests.post("https://api.opensolr.com/solr_manager/api/embed_and_search", data={
    "email": "YOUR_EMAIL", "api_key": "YOUR_API_KEY", "index_name": "my_index",
    "q": "how do I reset my password", "rows": 5, "in": "all", "fresh": "no"}, timeout=60)
for doc in r.json()["results"]["docs"]:
    print(doc["title"], doc["uri"])

Example Response

{
  "status": true,
  "results": {
    "docs": [
      {"id": "1b2b982f2b606ff5207066fa65c92c8f", "uri": "https://example.com/help/reset-password",
       "title": "Reset your password", "description": "...", "text": "...", "content_type": "text/html"}
    ],
    "num": 12, "hl": {"1b2b982f2b606ff5207066fa65c92c8f": {"text": ["... <em>reset</em> your <em>password</em> ..."]}},
    "facets": {}, "facet_pivot": {}, "stats": {}, "spellcheck": {}, "qtime": 41, "params": {}, "debug": {}
  },
  "embeddings": "[0.0384618304669857, 0.031014347448945045, ...]"
}

Use Cases

  • Retrieval for RAG: take the top 3–4 docs as context for ai_summary
  • A headless search UI (mobile app, SPA) that must rank exactly like the hosted search page
  • Semantic search inside your own product without running any embedding model

Related Documentation

Building RAG or semantic search on Opensolr? We are here to help.

Contact Support

Try it right now, without an account. There is a public demo account: email mcp@opensolr.com, API key 420b8b23e7b12dc8ab838932145a5065. The index mcp_demo_d1__dense is preloaded with 300 news articles, so search and grounded answers work the moment you connect, and you can create your own indexes on the account.

Anything you create there is deleted after 3 days. The account is shared with everyone — other people can change or delete your index, and you can do the same to theirs, so never put anything real in it. The limits are per index and deliberately small: 200 MB of bandwidth and 50 MB of disk. For an index that is private and stays put, create a free account — free forever, no card — and swap in your own two values.