mirror of
https://github.com/meilisearch/meilisearch.git
synced 2025-07-26 16:21:07 +00:00
Continue documenting and cleaning up the code
This commit is contained in:
@ -1,9 +1,19 @@
|
||||
/*! Module implementing the graph used for the graph-based ranking rules
|
||||
and its related algorithms.
|
||||
|
||||
A ranking rule graph is built on top of the [`QueryGraph`]: the nodes stay
|
||||
the same but the edges are replaced.
|
||||
*/
|
||||
|
||||
mod build;
|
||||
mod cheapest_paths;
|
||||
mod edge_docids_cache;
|
||||
mod empty_paths_cache;
|
||||
mod paths_map;
|
||||
|
||||
/// Implementation of the `proximity` ranking rule
|
||||
mod proximity;
|
||||
/// Implementation of the `typo` ranking rule
|
||||
mod typo;
|
||||
|
||||
pub use edge_docids_cache::EdgeDocidsCache;
|
||||
@ -17,30 +27,38 @@ use super::small_bitmap::SmallBitmap;
|
||||
use super::{QueryGraph, QueryNode, SearchContext};
|
||||
use crate::Result;
|
||||
|
||||
/// The condition that is associated with an edge in the ranking rule graph.
|
||||
///
|
||||
/// Some edges are unconditional, which means that traversing them does not reduce
|
||||
/// the set of candidates.
|
||||
///
|
||||
/// Most edges, however, have a condition attached to them. For example, for the
|
||||
/// proximity ranking rule, the condition could be that a word is N-close to another one.
|
||||
/// When the edge is traversed, some database operations are executed to retrieve the set
|
||||
/// of documents that satisfy the condition, which reduces the list of candidate document ids.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum EdgeDetails<E> {
|
||||
pub enum EdgeCondition<E> {
|
||||
Unconditional,
|
||||
Data(E),
|
||||
Conditional(E),
|
||||
}
|
||||
|
||||
/// An edge in the ranking rule graph.
|
||||
///
|
||||
/// It contains:
|
||||
/// 1. The source and destination nodes
|
||||
/// 2. The cost of traversing this edge
|
||||
/// 3. The condition associated with it
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Edge<E> {
|
||||
pub from_node: u16,
|
||||
pub to_node: u16,
|
||||
pub source_node: u16,
|
||||
pub dest_node: u16,
|
||||
pub cost: u8,
|
||||
pub details: EdgeDetails<E>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EdgePointer<'graph, E> {
|
||||
pub index: u16,
|
||||
pub edge: &'graph Edge<E>,
|
||||
pub condition: EdgeCondition<E>,
|
||||
}
|
||||
|
||||
// pub struct SubWordDerivations {
|
||||
// words: FxHashSet<Interned<String>>,
|
||||
// synonyms: FxHashSet<Interned<Phrase>>, // NO! they're phrases, not strings
|
||||
// split_words: bool,
|
||||
// phrases: FxHashSet<Interned<Phrase>>,
|
||||
// use_prefix_db: bool,
|
||||
// }
|
||||
|
||||
@ -74,46 +92,55 @@ pub struct EdgePointer<'graph, E> {
|
||||
// }
|
||||
|
||||
// fn word_derivations_used_by_edge<G: RankingRuleGraphTrait>(
|
||||
// edge: G::EdgeDetails,
|
||||
// edge: G::EdgeCondition,
|
||||
// ) -> SubWordDerivations {
|
||||
// todo!()
|
||||
// }
|
||||
|
||||
/// A trait to be implemented by a marker type to build a graph-based ranking rule.
|
||||
///
|
||||
/// It mostly describes how to:
|
||||
/// 1. Retrieve the set of edges (their cost and condition) between two nodes.
|
||||
/// 2. Compute the document ids satisfying a condition
|
||||
pub trait RankingRuleGraphTrait: Sized {
|
||||
/// The details of an edge connecting two query nodes. These details
|
||||
/// The condition of an edge connecting two query nodes. The condition
|
||||
/// should be sufficient to compute the edge's cost and associated document ids
|
||||
/// in [`compute_docids`](RankingRuleGraphTrait).
|
||||
type EdgeDetails: Sized + Clone;
|
||||
/// in [`resolve_edge_condition`](RankingRuleGraphTrait::resolve_edge_condition).
|
||||
type EdgeCondition: Sized + Clone;
|
||||
|
||||
/// A structure used in the construction of the graph, created when a
|
||||
/// query graph source node is visited. It is used to determine the cost
|
||||
/// and condition of a ranking rule edge when the destination node is visited.
|
||||
type BuildVisitedFromNode;
|
||||
|
||||
/// Return the label of the given edge details, to be used when visualising
|
||||
/// the ranking rule graph using GraphViz.
|
||||
fn graphviz_edge_details_label(edge: &Self::EdgeDetails) -> String;
|
||||
/// Return the label of the given edge condition, to be used when visualising
|
||||
/// the ranking rule graph.
|
||||
fn label_for_edge_condition(edge: &Self::EdgeCondition) -> String;
|
||||
|
||||
/// Compute the document ids associated with the given edge.
|
||||
fn compute_docids<'search>(
|
||||
/// Compute the document ids associated with the given edge condition,
|
||||
/// restricted to the given universe.
|
||||
fn resolve_edge_condition<'search>(
|
||||
ctx: &mut SearchContext<'search>,
|
||||
edge_details: &Self::EdgeDetails,
|
||||
edge_condition: &Self::EdgeCondition,
|
||||
universe: &RoaringBitmap,
|
||||
) -> Result<RoaringBitmap>;
|
||||
|
||||
/// Prepare to build the edges outgoing from `from_node`.
|
||||
/// Prepare to build the edges outgoing from `source_node`.
|
||||
///
|
||||
/// This call is followed by zero, one or more calls to [`build_visit_to_node`](RankingRuleGraphTrait::build_visit_to_node),
|
||||
/// This call is followed by zero, one or more calls to [`build_step_visit_destination_node`](RankingRuleGraphTrait::build_step_visit_destination_node),
|
||||
/// which builds the actual edges.
|
||||
fn build_visit_from_node<'search>(
|
||||
fn build_step_visit_source_node<'search>(
|
||||
ctx: &mut SearchContext<'search>,
|
||||
from_node: &QueryNode,
|
||||
source_node: &QueryNode,
|
||||
) -> Result<Option<Self::BuildVisitedFromNode>>;
|
||||
|
||||
/// Return the cost and details of the edges going from the previously visited node
|
||||
/// (with [`build_visit_from_node`](RankingRuleGraphTrait::build_visit_from_node)) to `to_node`.
|
||||
fn build_visit_to_node<'from_data, 'search: 'from_data>(
|
||||
/// Return the cost and condition of the edges going from the previously visited node
|
||||
/// (with [`build_step_visit_source_node`](RankingRuleGraphTrait::build_step_visit_source_node)) to `dest_node`.
|
||||
fn build_step_visit_destination_node<'from_data, 'search: 'from_data>(
|
||||
ctx: &mut SearchContext<'search>,
|
||||
to_node: &QueryNode,
|
||||
from_node_data: &'from_data Self::BuildVisitedFromNode,
|
||||
) -> Result<Vec<(u8, EdgeDetails<Self::EdgeDetails>)>>;
|
||||
dest_node: &QueryNode,
|
||||
source_node_data: &'from_data Self::BuildVisitedFromNode,
|
||||
) -> Result<Vec<(u8, EdgeCondition<Self::EdgeCondition>)>>;
|
||||
|
||||
fn log_state(
|
||||
graph: &RankingRuleGraph<Self>,
|
||||
@ -126,45 +153,32 @@ pub trait RankingRuleGraphTrait: Sized {
|
||||
);
|
||||
}
|
||||
|
||||
/// The graph used by graph-based ranking rules.
|
||||
///
|
||||
/// It is built on top of a [`QueryGraph`], keeping the same nodes
|
||||
/// but replacing the edges.
|
||||
pub struct RankingRuleGraph<G: RankingRuleGraphTrait> {
|
||||
pub query_graph: QueryGraph,
|
||||
// pub edges: Vec<HashMap<usize, Vec<Edge<G::EdgeDetails>>>>,
|
||||
pub all_edges: Vec<Option<Edge<G::EdgeDetails>>>,
|
||||
|
||||
pub node_edges: Vec<SmallBitmap>,
|
||||
|
||||
pub successors: Vec<SmallBitmap>,
|
||||
// TODO: to get the edges between two nodes:
|
||||
// 1. get node_outgoing_edges[from]
|
||||
// 2. get node_incoming_edges[to]
|
||||
// 3. take intersection betweem the two
|
||||
pub edges_store: Vec<Option<Edge<G::EdgeCondition>>>,
|
||||
pub edges_of_node: Vec<SmallBitmap>,
|
||||
}
|
||||
impl<G: RankingRuleGraphTrait> Clone for RankingRuleGraph<G> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
query_graph: self.query_graph.clone(),
|
||||
all_edges: self.all_edges.clone(),
|
||||
node_edges: self.node_edges.clone(),
|
||||
successors: self.successors.clone(),
|
||||
edges_store: self.edges_store.clone(),
|
||||
edges_of_node: self.edges_of_node.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
||||
pub fn remove_edge(&mut self, edge_index: u16) {
|
||||
let edge_opt = &mut self.all_edges[edge_index as usize];
|
||||
/// Remove the given edge from the ranking rule graph
|
||||
pub fn remove_ranking_rule_edge(&mut self, edge_index: u16) {
|
||||
let edge_opt = &mut self.edges_store[edge_index as usize];
|
||||
let Some(edge) = &edge_opt else { return };
|
||||
let (from_node, _to_node) = (edge.from_node, edge.to_node);
|
||||
let (source_node, _dest_node) = (edge.source_node, edge.dest_node);
|
||||
*edge_opt = None;
|
||||
|
||||
let from_node_edges = &mut self.node_edges[from_node as usize];
|
||||
from_node_edges.remove(edge_index);
|
||||
|
||||
let mut new_successors_from_node = SmallBitmap::new(self.all_edges.len() as u16);
|
||||
let all_edges = &self.all_edges;
|
||||
for from_node_edge in from_node_edges.iter() {
|
||||
let Edge { to_node, .. } = &all_edges[from_node_edge as usize].as_ref().unwrap();
|
||||
new_successors_from_node.insert(*to_node);
|
||||
}
|
||||
self.successors[from_node as usize] = new_successors_from_node;
|
||||
self.edges_of_node[source_node as usize].remove(edge_index);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user