--- title: Hybrid Search --- ParadeDB's full text and similarity search APIs can be combined in the same query to execute [hybrid search](/documentation/concepts/search#hybrid-search). This guide uses the `mock_items` table, which was created in the quickstart. It assumes that the entire [quickstart](/documentation/getting-started/quickstart) tutorial has been completed, including the vector search section. ## Reciprocal Rank Fusion Reciprocal rank fusion is a popular hybrid search algorithm that: 1. Calculates a BM25 and similarity score for the top `n` documents. 2. Ranks documents by their BM25 and similarity scores separately. The highest-ranked document for each score receives an `r` of `1`. 3. Calculates a reciprocal rank for each score as `1/(k + r)`, where `k` is a constant. `k` is usually set to `60`. 4. Calculates each document's reciprocal rank fusion score as the sum of the BM25 and similarity reciprocal rank scores. The following code block implements reciprocal rank fusion over the `mock_items` table. BM25 scores are calculated against the query `description:keyboard` and similarity scores are calculated against the vector `[1,2,3]`. ```sql WITH bm25_candidates AS ( SELECT id FROM mock_items WHERE description @@@ 'keyboard' ORDER BY paradedb.score(id) DESC LIMIT 20 ), bm25_ranked AS ( SELECT id, RANK() OVER (ORDER BY paradedb.score(id) DESC) AS rank FROM bm25_candidates ), semantic_search AS ( SELECT id, RANK() OVER (ORDER BY embedding <=> '[1,2,3]') AS rank FROM mock_items ORDER BY embedding <=> '[1,2,3]' LIMIT 20 ) SELECT COALESCE(semantic_search.id, bm25_ranked.id) AS id, COALESCE(1.0 / (60 + semantic_search.rank), 0.0) + COALESCE(1.0 / (60 + bm25_ranked.rank), 0.0) AS score, mock_items.description, mock_items.embedding FROM semantic_search FULL OUTER JOIN bm25_ranked ON semantic_search.id = bm25_ranked.id JOIN mock_items ON mock_items.id = COALESCE(semantic_search.id, bm25_ranked.id) ORDER BY score DESC, description LIMIT 5; ``` ```csv id | score | description | embedding ----+------------------------+--------------------------+----------- 1 | 0.03062178588125292193 | Ergonomic metal keyboard | [3,4,5] 2 | 0.02990695613646433318 | Plastic Keyboard | [4,5,6] 19 | 0.01639344262295081967 | Artistic ceramic vase | [1,2,3] 29 | 0.01639344262295081967 | Designer wall paintings | [1,2,3] 39 | 0.01639344262295081967 | Handcrafted wooden frame | [1,2,3] (5 rows) ``` Here, we see that the top five results either contain `keyboard` in the `description` field or have an `embedding` of `[1,2,3]`.