/search-types
Constructing prefetch queries for hybrid retrieval, including BM25/dense and multi-field setups, and choosing a lexical retrieval method. Use when someone asks 'dense and sparse in one search?', 'how to combine multiple fields for retrieval?', 'payloads or sparse vectors for
Claude Code
$ npx -y skills add qdrant/skills --skill search-types --agent claude-code
Codex
$ npx skills add qdrant/skills --skill search-types -a codex -y
Cursor
$ npx skills add qdrant/skills --skill search-types -a cursor -y
Gemini CLI
$ npx skills add qdrant/skills --skill search-types -a gemini-cli -y
GitHub Copilot
$ npx skills add qdrant/skills --skill search-types -a github-copilot -y
OpenCode
$ npx skills add qdrant/skills --skill search-types -a opencode -y
Windsurf
$ npx skills add qdrant/skills --skill search-types -a windsurf -y
SKILL.md
search-types.SKILL.mdname: qdrant-hybrid-search-prefetches
description: "Constructing prefetch queries for hybrid retrieval, including BM25/dense and multi-field setups, and choosing a lexical retrieval method. Use when someone asks 'dense and sparse in one search?', 'how to combine multiple fields for retrieval?', 'payloads or sparse vectors for lexical?', 'BM25 on a full-text index or sparse vectors?', 'which sparse embedding model to use?', 'BM25 vs SPLADE?', or 'how to migrate BM25 sparse vectors to a text index?'"
Different Searches in One Query API Request
Each `prefetch` runs exactly one search per one query.
Understand if user wants to run several parallel searches on: 1. The same vector representations but different queries or filters. 2. Different vector representations but the same raw query.
If first, help user to design logic of constructing query or/and filters on application side and then check [Combining Searches](../combining-searches/SKILL.md). Don't forget to create [indices on filterable payload fields](https://skills.qdrant.tech/md/documentation/manage-data/indexing/?s=payload-index), immediately after collection creation, prior to building HNSW, so filterable HNSW could be constructed.
If second, use [named vectors](https://skills.qdrant.tech/md/documentation/manage-data/vectors/?s=named-vectors), which allow to store multiple vector types per point in one collection. On Qdrant 1.18 or newer, named vectors can be added to or removed from an existing collection without recreating it [Update vector schema](https://skills.qdrant.tech/md/documentation/manage-data/collections/?s=update-vector-schema); on 1.17 or older, they can be configured only at collection creation. To choose vectors, check following recommendations.
Missed Keyword Matches
Use when: pure vector search misses exact term or keyword matches and you need lexical retrieval alongside semantic search.
Most likely you need a lexical retriever alongside the dense one. [Payload filtering doesn't provide any ranking score](https://skills.qdrant.tech/md/documentation/search/text-search/?s=filtering-versus-querying), so rank text with BM25 or a sparse vector.
Choose a Lexical Retriever for Text
- **BM25 on a full-text index** (Qdrant 1.20 or newer, recommended default). Create a `text` payload index with `scoring` enabled and query it with a `text` query (`using` set to the field name). It indexes text already in the payload, so there are no embeddings and no re-upload, and it computes the average document length from your data. The index defaults to no stemming and no stopwords, so configure the language. Scoring costs extra memory and disk. [BM25 on a full-text index](https://skills.qdrant.tech/md/documentation/search/text-search/full-text-search/?s=bm25) [BM25 scoring index](https://skills.qdrant.tech/md/documentation/manage-data/indexing/?s=bm25-scoring)
- **BM25 sparse vector model**, built into Qdrant core (computed server-side by the `qdrant/bm25` inference model or client-side with FastEmbed). Use it on Qdrant 1.19 or older, when the text isn't stored in the payload, or when you need the sparse vector itself, for example for Edge compatibility. Good baseline, works out-of-domain, usually for long texts. Can be used for non-English content with per-language configuration. More in [Sparse Vector BM25](https://skills.qdrant.tech/md/documentation/search/text-search/sparse-vector-search/?s=bm25)
- **BM42** learned sparse, based on BM25, but better for small chunks of text & with meaning understanding. Works only on English. Requires fine-tuning for domain-specific retrieval. Requires FastEmbed (Python/REST only, not available in all SDKs). Not maintained.
- **miniCOIL** learned sparse, BM25 with additional understanding of words meaning in context. Works only on English. Requires fine-tuning for domain-specific retrieval. Requires FastEmbed. Usage shown in [FastEmbed miniCOIL documentation](https://skills.qdrant.tech/md/documentation/fastembed/fastembed-minicoil/).
- **SPLADE++** learned sparse with term expansion. Heavier inference and resources usage but better performance due to term expansion. Requires fine-tuning for domain-specific retrieval. Provided in Qdrant Cloud Inference and FastEmbed versions work only on English. To use with FastEmbed, check [FastEmbed SPLADE documentation](https://skills.qdrant.tech/md/documentation/fastembed/fastembed-splade/).
- **External learned sparse embeddings**, for example BAAI/bge-m3.
What to remember when using any lexical retriever:
- tokenization and stemming affect exact matches, especially on custom codes, terms, etc.
- On Qdrant 1.18 and older, IDF statistics are computed over the whole shard, which distorts scoring in multi-tenant collections where tenants have different vocabularies. On 1.19 or newer, scope them to one tenant with the `idf` search parameter, and index the tenant field. On 1.20 or newer this also applies to BM25 `text` queries on a full-text index. See [Per-tenant scoring statistics](https://skills.qdrant.tech/md/documentation/manage-data/multitenancy/?s=per-tenant-scoring-statistics).
- BM25 might be not good for small chunks of text, as BM25 algorithm was initially created for search on long documents; consider adjusting document statistics (TF & IDF, k, b).
- Statistics are per shard, and deleted or updated points can skew them slightly until the optimizer rebuilds segments, so scores can shift without a data change [Corpus statistics](https://skills.qdrant.tech/md/documentation/search/text-search/full-text-search/?s=corpus-statistics).
What to remember when using BM25 on a full-text index:
- Set stemmer and stopwords for the data's language on the index. Without them, BM25 matches only exact lowercased tokens. For language-neutral content (names, codes) use the `multilingual` tokenizer and leave stemming and stopwords off [Text processing](https://skills.qdrant.tech/md/documentation/search/text-search/full-text-search/?s=text-proces
Read more
name: qdrant-hybrid-search-prefetches description: "Constructing prefetch queries for hybrid retrieval, including BM25/dense and multi-field setups, and choosing a lexical retrieval method. Use when someone asks 'dense and sparse in one search?', 'how to combine multiple fields for retrieval?', 'payloads or sparse vectors for lexical?', 'BM25 on a full-text index or sparse vectors?', 'which sparse embedding model to use?', 'BM25 vs SPLADE?', or 'how to migrate BM25 sparse vectors to a text index?'"
Different Searches in One Query API Request
Each `prefetch` runs exactly one search per one query.
Understand if user wants to run several parallel searches on: 1. The same vector representations but different queries or filters. 2. Different vector representations but the same raw query.
If first, help user to design logic of constructing query or/and filters on application side and then check [Combining Searches](../combining-searches/SKILL.md). Don't forget to create [indices on filterable payload fields](https://skills.qdrant.tech/md/documentation/manage-data/indexing/?s=payload-index), immediately after collection creation, prior to building HNSW, so filterable HNSW could be constructed.
If second, use [named vectors](https://skills.qdrant.tech/md/documentation/manage-data/vectors/?s=named-vectors), which allow to store multiple vector types per point in one collection. On Qdrant 1.18 or newer, named vectors can be added to or removed from an existing collection without recreating it [Update vector schema](https://skills.qdrant.tech/md/documentation/manage-data/collections/?s=update-vector-schema); on 1.17 or older, they can be configured only at collection creation. To choose vectors, check following recommendations.
Missed Keyword Matches
Use when: pure vector search misses exact term or keyword matches and you need lexical retrieval alongside semantic search.
Most likely you need a lexical retriever alongside the dense one. [Payload filtering doesn't provide any ranking score](https://skills.qdrant.tech/md/documentation/search/text-search/?s=filtering-versus-querying), so rank text with BM25 or a sparse vector.
Choose a Lexical Retriever for Text
- **BM25 on a full-text index** (Qdrant 1.20 or newer, recommended default). Create a `text` payload index with `scoring` enabled and query it with a `text` query (`using` set to the field name). It indexes text already in the payload, so there are no embeddings and no re-upload, and it computes the average document length from your data. The index defaults to no stemming and no stopwords, so configure the language. Scoring costs extra memory and disk. [BM25 on a full-text index](https://skills.qdrant.tech/md/documentation/search/text-search/full-text-search/?s=bm25) [BM25 scoring index](https://skills.qdrant.tech/md/documentation/manage-data/indexing/?s=bm25-scoring)
- **BM25 sparse vector model**, built into Qdrant core (computed server-side by the `qdrant/bm25` inference model or client-side with FastEmbed). Use it on Qdrant 1.19 or older, when the text isn't stored in the payload, or when you need the sparse vector itself, for example for Edge compatibility. Good baseline, works out-of-domain, usually for long texts. Can be used for non-English content with per-language configuration. More in [Sparse Vector BM25](https://skills.qdrant.tech/md/documentation/search/text-search/sparse-vector-search/?s=bm25)
- **BM42** learned sparse, based on BM25, but better for small chunks of text & with meaning understanding. Works only on English. Requires fine-tuning for domain-specific retrieval. Requires FastEmbed (Python/REST only, not available in all SDKs). Not maintained.
- **miniCOIL** learned sparse, BM25 with additional understanding of words meaning in context. Works only on English. Requires fine-tuning for domain-specific retrieval. Requires FastEmbed. Usage shown in [FastEmbed miniCOIL documentation](https://skills.qdrant.tech/md/documentation/fastembed/fastembed-minicoil/).
- **SPLADE++** learned sparse with term expansion. Heavier inference and resources usage but better performance due to term expansion. Requires fine-tuning for domain-specific retrieval. Provided in Qdrant Cloud Inference and FastEmbed versions work only on English. To use with FastEmbed, check [FastEmbed SPLADE documentation](https://skills.qdrant.tech/md/documentation/fastembed/fastembed-splade/).
- **External learned sparse embeddings**, for example BAAI/bge-m3.
What to remember when using any lexical retriever:
- tokenization and stemming affect exact matches, especially on custom codes, terms, etc.
- On Qdrant 1.18 and older, IDF statistics are computed over the whole shard, which distorts scoring in multi-tenant collections where tenants have different vocabularies. On 1.19 or newer, scope them to one tenant with the `idf` search parameter, and index the tenant field. On 1.20 or newer this also applies to BM25 `text` queries on a full-text index. See [Per-tenant scoring statistics](https://skills.qdrant.tech/md/documentation/manage-data/multitenancy/?s=per-tenant-scoring-statistics).
- BM25 might be not good for small chunks of text, as BM25 algorithm was initially created for search on long documents; consider adjusting document statistics (TF & IDF, k, b).
- Statistics are per shard, and deleted or updated points can skew them slightly until the optimizer rebuilds segments, so scores can shift without a data change [Corpus statistics](https://skills.qdrant.tech/md/documentation/search/text-search/full-text-search/?s=corpus-statistics).
What to remember when using BM25 on a full-text index:
- Set stemmer and stopwords for the data's language on the index. Without them, BM25 matches only exact lowercased tokens. For language-neutral content (names, codes) use the `multilingual` tokenizer and leave stemming and stopwords off [Text processing](https://skills.qdrant.tech/md/documentation/search/text-search/full-text-search/?s=text-proces
Agent skills for building with Qdrant vector search Skills encode deep Qdrant knowledge so coding agents can make the engineering decisions that determine whether vector search works well: quantization, sharding, tenant isolation, hybrid search, model
Other skills on qdrant.
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about search-types.
- Which coding agents can use search-types?
- search-types installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

