Qdrant Multi-keyword full-text search returns incomplete results #21952

Closed
opened 2026-02-21 20:15:01 -05:00 by yindo · 1 comment
Owner

Originally created by @euxx on GitHub (Jan 28, 2026).

Self Checks

  • I have read the Contributing Guide and Language Policy.
  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report, otherwise it will be closed.
  • Please do not modify this template :) and fill in all the required fields.

1. Is this request related to a challenge you're experiencing? Tell me about your story.

When using Qdrant's search_by_full_text method with multiple keywords (e.g., "apple banana"), the search only returns documents containing all keywords instead of documents containing any keyword.

For example:

Searching "apple" returns documents A (with "apple")
Searching "banana" returns documents B (with "banana")
Searching "apple banana" only returns documents containing both keywords, missing A and B

This happens because Qdrant's MatchText uses AND logic by default, unlike Elasticsearch/OpenSearch which use OR logic for multi-word match queries.

2. Additional context or comments

Root Cause:

Qdrant's MatchText with multiple words uses AND logic (all words must match)

The original docstring incorrectly stated "BM25" - Qdrant < 1.10 doesn't support native BM25

Current Qdrant image is langgenius/qdrant:v1.8.3

Solution:

Search each keyword separately and merge results with deduplication

This aligns with the behavior of other vector databases (ES/OpenSearch)

3. Can you help us with this feature?

  • I am interested in contributing to this feature.
Originally created by @euxx on GitHub (Jan 28, 2026). ### Self Checks - [x] I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542). - [x] I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones. - [x] I confirm that I am using English to submit this report, otherwise it will be closed. - [x] Please do not modify this template :) and fill in all the required fields. ### 1. Is this request related to a challenge you're experiencing? Tell me about your story. When using Qdrant's `search_by_full_text` method with multiple keywords (e.g., "apple banana"), the search only returns documents containing all keywords instead of documents containing any keyword. For example: Searching "apple" returns documents A (with "apple") Searching "banana" returns documents B (with "banana") Searching "apple banana" only returns documents containing both keywords, missing A and B This happens because Qdrant's `MatchText` uses AND logic by default, unlike Elasticsearch/OpenSearch which use OR logic for multi-word match queries. ### 2. Additional context or comments #### Root Cause: Qdrant's `MatchText` with multiple words uses AND logic (all words must match) The original docstring incorrectly stated "BM25" - Qdrant < 1.10 doesn't support native BM25 Current Qdrant image is `langgenius/qdrant:v1.8.3` #### Solution: Search each keyword separately and merge results with deduplication This aligns with the behavior of other vector databases (ES/OpenSearch) ### 3. Can you help us with this feature? - [x] I am interested in contributing to this feature.
yindo added the 👻 feat:rag label 2026-02-21 20:15:01 -05:00
yindo closed this issue 2026-02-21 20:15:01 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Jan 28, 2026):

Qdrant's current full-text search uses AND logic for multi-keyword queries, so only documents containing all keywords are returned. This differs from Elasticsearch/OpenSearch, which use OR logic and return documents containing any of the keywords. The proposed solution is to split the query into individual keywords, perform separate searches for each, and then merge and deduplicate the results—this would align Qdrant's behavior with other vector databases and provide more complete results for multi-keyword searches.

To implement this in Dify, you would update the Qdrant integration in api/core/rag/datasource/vdb/qdrant/qdrant_vector.py, specifically the QdrantVector.search_by_full_text method. The steps are: parse the query into keywords, run a Qdrant search for each keyword, merge the resulting Document objects, deduplicate them (using the _filter_duplicate_texts utility from BaseVector), and finally apply any top_k or score limits as needed. Dify's retrieval pipeline already has robust aggregation and deduplication logic (see DatasetRetrieval and DatasetMultiRetrieverTool), which you can reference for best practices on merging results and avoiding duplicates source.

There are no recent PRs implementing this for Qdrant, but similar improvements have been made for other vector integrations. Related issues (#1542, #16963) show ongoing community interest and confirm that contributions are welcome. Be sure to test that the new logic returns all relevant documents for multi-keyword queries and that deduplication is robust, especially when documents match multiple keywords source.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

@dosubot[bot] commented on GitHub (Jan 28, 2026): <!-- Answer --> Qdrant's current full-text search uses AND logic for multi-keyword queries, so only documents containing all keywords are returned. This differs from Elasticsearch/OpenSearch, which use OR logic and return documents containing any of the keywords. The proposed solution is to split the query into individual keywords, perform separate searches for each, and then merge and deduplicate the results—this would align Qdrant's behavior with other vector databases and provide more complete results for multi-keyword searches. To implement this in Dify, you would update the Qdrant integration in `api/core/rag/datasource/vdb/qdrant/qdrant_vector.py`, specifically the `QdrantVector.search_by_full_text` method. The steps are: parse the query into keywords, run a Qdrant search for each keyword, merge the resulting Document objects, deduplicate them (using the `_filter_duplicate_texts` utility from `BaseVector`), and finally apply any top_k or score limits as needed. Dify's retrieval pipeline already has robust aggregation and deduplication logic (see `DatasetRetrieval` and `DatasetMultiRetrieverTool`), which you can reference for best practices on merging results and avoiding duplicates [source](https://github.com/langgenius/dify/blob/e98c1adfbf8b94adede7cb6abd98ee8ca222ddf9/api/core/rag/retrieval/dataset_retrieval.py#L77-L1520). There are no recent PRs implementing this for Qdrant, but similar improvements have been made for other vector integrations. Related issues (#1542, #16963) show ongoing community interest and confirm that contributions are welcome. Be sure to test that the new logic returns all relevant documents for multi-keyword queries and that deduplication is robust, especially when documents match multiple keywords [source](https://github.com/langgenius/dify/blob/e98c1adfbf8b94adede7cb6abd98ee8ca222ddf9/api/core/rag/datasource/vdb/qdrant/qdrant_vector.py#L341-L435). <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/4c8e4d2e-1e94-4a48-9153-25c8b693208a?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/4c8e4d2e-1e94-4a48-9153-25c8b693208a?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/4c8e4d2e-1e94-4a48-9153-25c8b693208a?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/4c8e4d2e-1e94-4a48-9153-25c8b693208a?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/4c8e4d2e-1e94-4a48-9153-25c8b693208a?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/4c8e4d2e-1e94-4a48-9153-25c8b693208a?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/4c8e4d2e-1e94-4a48-9153-25c8b693208a?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/6088a4f4-073a-43f3-b3d4-4f06fb0c05a0/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=Qdrant%27s%20current%20full-text%20search%20uses%20AND%20logic%20for%20multi-keyword%20queries%2C%20so%20only%20documents%20containing%20all%20keywords%20are%20returned.%20This%20differs%20from%20Elasticsearch/OpenSearch%2C%20which%20use%20OR%20logic%20and%20return%20documents%20containing%20any%20of%20the%20keywords.%20The%20proposed%20solution%20is%20to%20split%20the%20query%20into%20individual%20keywords%2C%20perform%20separate%20searches%20for%20each%2C%20and%20then%20merge%20and%20deduplicate%20the%20results%E2%80%94this%20would%20align%20Qdrant%27s%20behavior%20with%20other%20vector%20databases%20and%20provide%20more%20complete%20results%20for%20multi-keyword%20searches.%0A%0ATo%20implement%20this%20in%20Dify%2C%20you%20would%20update%20the%20Qdrant%20integration%20in%20%60api/core/rag/datasource/vdb/qdrant/qdrant_vector.py%60%2C%20specifically%20the%20%60QdrantVector.search_by_full_text%60%20method.%20The%20steps%20are%3A%20parse%20the%20query%20into%20keywords%2C%20run%20a%20Qdrant%20search%20for%20each%20keyword%2C%20merge%20the%20resulting%20Document%20objects%2C%20deduplicate%20them%20%28using%20the%20%60_filter_duplicate_texts%60%20utility%20from%20%60BaseVector%60%29%2C%20and%20finally%20apply%20any%20top_k%20or%20score%20limits%20as%20needed.%20Dify%27s%20retrieval%20pipeline%20already%20has%20robust%20aggregation%20and%20deduplication%20logic%20%28see%20%60DatasetRetrieval%60%20and%20%60DatasetMultiRetrieverTool%60%29%2C%20which%20you%20can%20reference%20for%20best%20practices%20on%20merging%20results%20and%20avoiding%20duplicates%20%5Bsource%5D%28https%3A//github.com/langgenius/dify/blob/e98c1adfbf8b94adede7cb6abd98ee8ca222ddf9/api/core/rag/retrieval/dataset_retrieval.py%23L77-L1520%29.%0A%0AThere%20are%20no%20recent%20PRs%20implementing%20this%20for%20Qdrant%2C%20but%20similar%20improvements%20have%20been%20made%20for%20other%20vector%20integrations.%20Related%20issues%20%28%231542%2C%20%2316963%29%20show%20ongoing%20community%20interest%20and%20confirm%20that%20contributions%20are%20welcome.%20Be%20sure%20to%20test%20that%20the%20new%20logic%20returns%20all%20relevant%20documents%20for%20multi-keyword%20queries%20and%20that%20deduplication%20is%20robust%2C%20especially%20when%20documents%20match%20multiple%20keywords%20%5Bsource%5D%28https%3A//github.com/langgenius/dify/blob/e98c1adfbf8b94adede7cb6abd98ee8ca222ddf9/api/core/rag/datasource/vdb/qdrant/qdrant_vector.py%23L341-L435%29.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/langgenius/dify/issues/31657)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify#21952