class_docstr: A component that joins input lists of Documents from multiple connections and outputs them as one list.
  
  The component allows multiple join modes:
  * concatenate: Combine Documents from multiple components. Discards duplicate Documents.
                  Documents get their scores from the last component in the pipeline that assigns scores.
                  This join mode doesn't influence Document scores.
  * merge: Merge scores of duplicate Documents coming from multiple components.
          Optionally, you can assign a weight to the scores and set the top_k limit for this join mode.
          You can also use this join mode to rerank retrieved Documents.
  * reciprocal_rank_fusion: Combine Documents into a single list based on their ranking received from multiple components.
  
  Example usage in a hybrid retrieval pipeline:
  ```python
  document_store = InMemoryDocumentStore()
  p = Pipeline()
  p.add_component(instance=InMemoryBM25Retriever(document_store=document_store), name="bm25_retriever")
  p.add_component(
          instance=SentenceTransformersTextEmbedder(model="sentence-transformers/all-MiniLM-L6-v2"),
          name="text_embedder",
      )
  p.add_component(instance=InMemoryEmbeddingRetriever(document_store=document_store), name="embedding_retriever")
  p.add_component(instance=DocumentJoiner(), name="joiner")
  p.connect("bm25_retriever", "joiner")
  p.connect("embedding_retriever", "joiner")
  p.connect("text_embedder", "embedding_retriever")
  query = "What is the capital of France?"
  p.run(data={"bm25_retriever": {"query": query},
              "text_embedder": {"text": query}})
  ```
class_docstr_tok: ["A","component","that","joins","input","lists","of","Documents","from","multiple","connections","and","outputs","them","as","one","list",".","The","component","allows","multiple","join","modes",":","*","concatenate",":","Combine","Documents","from","multiple","components",".","Discards","duplicate","Documents",".","Documents","get","their","scores","from","the","last","component","in","the","pipeline","that","assigns","scores",".","This","join","mode","does","n't","influence","Document","scores",".","*","merge",":","Merge","scores","of","duplicate","Documents","coming","from","multiple","components",".","Optionally",",","you","can","assign","a","weight","to","the","scores","and","set","the","top_k","limit","for","this","join","mode",".","You","can","also","use","this","join","mode","to","rerank","retrieved","Documents",".","*","reciprocal_rank_fusion",":","Combine","Documents","into","a","single","list","based","on","their","ranking","received","from","multiple","components",".","Example","usage","in","a","hybrid","retrieval","pipeline",":","``","`","python","document_store","=","InMemoryDocumentStore","(",")","p","=","Pipeline","(",")","p.add_component","(","instance=InMemoryBM25Retriever","(","document_store=document_store",")",",","name=","''","bm25_retriever","''",")","p.add_component","(","instance=SentenceTransformersTextEmbedder","(","model=","''","sentence-transformers\/all-MiniLM-L6-v2","''",")",",","name=","''","text_embedder","''",",",")","p.add_component","(","instance=InMemoryEmbeddingRetriever","(","document_store=document_store",")",",","name=","''","embedding_retriever","''",")","p.add_component","(","instance=DocumentJoiner","(",")",",","name=","''","joiner","''",")","p.connect","(","``","bm25_retriever","''",",","``","joiner","''",")","p.connect","(","``","embedding_retriever","''",",","``","joiner","''",")","p.connect","(","``","text_embedder","''",",","``","embedding_retriever","''",")","query","=","``","What","is","the","capital","of","France","?","''","p.run","(","data=","{","``","bm25_retriever","''",":","{","``","query","''",":","query","}",",","``","text_embedder","''",":","{","``","text","''",":","query","}","}",")","``","`"]
docstr: Merge multiple lists of Documents and assign scores based on reciprocal rank fusion.
  The constant k is set to 61 (60 was suggested by the original paper,
  plus 1 as python lists are 0-based and the paper used 1-based ranking).
docstr_tok: ["Merge","multiple","lists","of","Documents","and","assign","scores","based","on","reciprocal","rank","fusion",".","The","constant","k","is","set","to","61","(","60","was","suggested","by","the","original","paper",",","plus","1","as","python","lists","are","0-based","and","the","paper","used","1-based","ranking",")","."]
code: def _reciprocal_rank_fusion(self, document_lists):
      """
      Merge multiple lists of Documents and assign scores based on reciprocal rank fusion.
      The constant k is set to 61 (60 was suggested by the original paper,
      plus 1 as python lists are 0-based and the paper used 1-based ranking).
      """
      k = 61
  
      scores_map = defaultdict(int)
      documents_map = {}
      for documents in document_lists:
          for rank, doc in enumerate(documents):
              scores_map[doc.id] += 1 / (k + rank)
              documents_map[doc.id] = doc
  
      for doc in documents_map.values():
          doc.score = scores_map[doc.id]
  
      return documents_map.values()
  
file_path: haystack/haystack/components/joiners/document_joiner.py
imports: import itertools
  import logging
  from collections import defaultdict
  from math import inf
  from typing import List, Optional
  from haystack.core.component.types import Variadic
  from haystack import component, Document
label_desc: Use image node_id 5 for calling the DocumentJoiner obj's underlying member method code with example usage: obj._reciprocal_rank_fusion(document_lists) and returns: documents_map