mirror of
https://github.com/meilisearch/meilisearch.git
synced 2025-08-01 03:10:04 +00:00
Simplify graph-based ranking rule impl
This commit is contained in:
@ -1,7 +1,6 @@
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
use std::collections::btree_map::Entry;
|
||||
use std::collections::{BTreeMap, VecDeque};
|
||||
use std::collections::{BTreeSet, VecDeque};
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use super::{DeadEndsCache, RankingRuleGraph, RankingRuleGraphTrait};
|
||||
@ -15,8 +14,8 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
||||
&mut self,
|
||||
from: Interned<QueryNode>,
|
||||
cost: u16,
|
||||
all_distances: &MappedInterner<Vec<(u16, SmallBitmap<G::Condition>)>, QueryNode>,
|
||||
dead_end_path_cache: &mut DeadEndsCache<G::Condition>,
|
||||
all_distances: &MappedInterner<Vec<u16>, QueryNode>,
|
||||
dead_ends_cache: &mut DeadEndsCache<G::Condition>,
|
||||
mut visit: impl FnMut(
|
||||
&[Interned<G::Condition>],
|
||||
&mut Self,
|
||||
@ -27,11 +26,11 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
||||
from,
|
||||
cost,
|
||||
all_distances,
|
||||
dead_end_path_cache,
|
||||
dead_ends_cache,
|
||||
&mut visit,
|
||||
&mut vec![],
|
||||
&mut SmallBitmap::for_interned_values_in(&self.conditions_interner),
|
||||
dead_end_path_cache.forbidden.clone(),
|
||||
dead_ends_cache.forbidden.clone(),
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
@ -39,8 +38,8 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
||||
&mut self,
|
||||
from: Interned<QueryNode>,
|
||||
cost: u16,
|
||||
all_distances: &MappedInterner<Vec<(u16, SmallBitmap<G::Condition>)>, QueryNode>,
|
||||
dead_end_path_cache: &mut DeadEndsCache<G::Condition>,
|
||||
all_distances: &MappedInterner<Vec<u16>, QueryNode>,
|
||||
dead_ends_cache: &mut DeadEndsCache<G::Condition>,
|
||||
visit: &mut impl FnMut(
|
||||
&[Interned<G::Condition>],
|
||||
&mut Self,
|
||||
@ -62,7 +61,7 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
||||
None => {
|
||||
if edge.dest_node == self.query_graph.end_node {
|
||||
any_valid = true;
|
||||
let control_flow = visit(prev_conditions, self, dead_end_path_cache)?;
|
||||
let control_flow = visit(prev_conditions, self, dead_ends_cache)?;
|
||||
match control_flow {
|
||||
ControlFlow::Continue(_) => {}
|
||||
ControlFlow::Break(_) => return Ok(true),
|
||||
@ -73,7 +72,7 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
||||
edge.dest_node,
|
||||
cost - edge.cost as u16,
|
||||
all_distances,
|
||||
dead_end_path_cache,
|
||||
dead_ends_cache,
|
||||
visit,
|
||||
prev_conditions,
|
||||
cur_path,
|
||||
@ -83,12 +82,10 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
||||
}
|
||||
Some(condition) => {
|
||||
if forbidden_conditions.contains(condition)
|
||||
|| !all_distances.get(edge.dest_node).iter().any(
|
||||
|(next_cost, necessary_conditions)| {
|
||||
(*next_cost == cost - edge.cost as u16)
|
||||
&& !forbidden_conditions.intersects(necessary_conditions)
|
||||
},
|
||||
)
|
||||
|| all_distances
|
||||
.get(edge.dest_node)
|
||||
.iter()
|
||||
.all(|next_cost| *next_cost != cost - edge.cost as u16)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -96,14 +93,14 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
||||
prev_conditions.push(condition);
|
||||
let mut new_forbidden_conditions = forbidden_conditions.clone();
|
||||
if let Some(next_forbidden) =
|
||||
dead_end_path_cache.forbidden_conditions_after_prefix(prev_conditions)
|
||||
dead_ends_cache.forbidden_conditions_after_prefix(prev_conditions)
|
||||
{
|
||||
new_forbidden_conditions.union(&next_forbidden);
|
||||
}
|
||||
|
||||
let next_any_valid = if edge.dest_node == self.query_graph.end_node {
|
||||
any_valid = true;
|
||||
let control_flow = visit(prev_conditions, self, dead_end_path_cache)?;
|
||||
let control_flow = visit(prev_conditions, self, dead_ends_cache)?;
|
||||
match control_flow {
|
||||
ControlFlow::Continue(_) => {}
|
||||
ControlFlow::Break(_) => return Ok(true),
|
||||
@ -114,7 +111,7 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
||||
edge.dest_node,
|
||||
cost - edge.cost as u16,
|
||||
all_distances,
|
||||
dead_end_path_cache,
|
||||
dead_ends_cache,
|
||||
visit,
|
||||
prev_conditions,
|
||||
cur_path,
|
||||
@ -129,8 +126,8 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
||||
any_valid |= next_any_valid;
|
||||
|
||||
if next_any_valid {
|
||||
forbidden_conditions = dead_end_path_cache
|
||||
.forbidden_conditions_for_all_prefixes_up_to(prev_conditions);
|
||||
forbidden_conditions =
|
||||
dead_ends_cache.forbidden_conditions_for_all_prefixes_up_to(prev_conditions);
|
||||
if cur_path.intersects(&forbidden_conditions) {
|
||||
break 'edges_loop;
|
||||
}
|
||||
@ -140,16 +137,13 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
||||
Ok(any_valid)
|
||||
}
|
||||
|
||||
pub fn initialize_distances_with_necessary_edges(
|
||||
&self,
|
||||
) -> MappedInterner<Vec<(u16, SmallBitmap<G::Condition>)>, QueryNode> {
|
||||
pub fn initialize_distances_with_necessary_edges(&self) -> MappedInterner<Vec<u16>, QueryNode> {
|
||||
let mut distances_to_end = self.query_graph.nodes.map(|_| vec![]);
|
||||
let mut enqueued = SmallBitmap::new(self.query_graph.nodes.len());
|
||||
|
||||
let mut node_stack = VecDeque::new();
|
||||
|
||||
*distances_to_end.get_mut(self.query_graph.end_node) =
|
||||
vec![(0, SmallBitmap::for_interned_values_in(&self.conditions_interner))];
|
||||
*distances_to_end.get_mut(self.query_graph.end_node) = vec![0];
|
||||
|
||||
for prev_node in self.query_graph.nodes.get(self.query_graph.end_node).predecessors.iter() {
|
||||
node_stack.push_back(prev_node);
|
||||
@ -157,35 +151,20 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
||||
}
|
||||
|
||||
while let Some(cur_node) = node_stack.pop_front() {
|
||||
let mut self_distances = BTreeMap::<u16, SmallBitmap<G::Condition>>::new();
|
||||
let mut self_distances = BTreeSet::<u16>::new();
|
||||
|
||||
let cur_node_edges = &self.edges_of_node.get(cur_node);
|
||||
for edge_idx in cur_node_edges.iter() {
|
||||
let edge = self.edges_store.get(edge_idx).as_ref().unwrap();
|
||||
let succ_node = edge.dest_node;
|
||||
let succ_distances = distances_to_end.get(succ_node);
|
||||
for (succ_distance, succ_necessary_conditions) in succ_distances {
|
||||
let mut potential_necessary_edges =
|
||||
SmallBitmap::for_interned_values_in(&self.conditions_interner);
|
||||
for condition in
|
||||
edge.condition.into_iter().chain(succ_necessary_conditions.iter())
|
||||
{
|
||||
potential_necessary_edges.insert(condition);
|
||||
}
|
||||
|
||||
match self_distances.entry(edge.cost as u16 + succ_distance) {
|
||||
Entry::Occupied(mut prev_necessary_edges) => {
|
||||
prev_necessary_edges.get_mut().intersection(&potential_necessary_edges);
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(potential_necessary_edges);
|
||||
}
|
||||
}
|
||||
for succ_distance in succ_distances {
|
||||
self_distances.insert(edge.cost as u16 + succ_distance);
|
||||
}
|
||||
}
|
||||
let distances_to_end_cur_node = distances_to_end.get_mut(cur_node);
|
||||
for (cost, necessary_edges) in self_distances.iter() {
|
||||
distances_to_end_cur_node.push((*cost, necessary_edges.clone()));
|
||||
for cost in self_distances.iter() {
|
||||
distances_to_end_cur_node.push(*cost);
|
||||
}
|
||||
*distances_to_end.get_mut(cur_node) = self_distances.into_iter().collect();
|
||||
for prev_node in self.query_graph.nodes.get(cur_node).predecessors.iter() {
|
||||
|
@ -112,9 +112,9 @@ pub trait RankingRuleGraphTrait: Sized {
|
||||
fn log_state(
|
||||
graph: &RankingRuleGraph<Self>,
|
||||
paths: &[Vec<Interned<Self::Condition>>],
|
||||
dead_end_path_cache: &DeadEndsCache<Self::Condition>,
|
||||
dead_ends_cache: &DeadEndsCache<Self::Condition>,
|
||||
universe: &RoaringBitmap,
|
||||
distances: &MappedInterner<Vec<(u16, SmallBitmap<Self::Condition>)>, QueryNode>,
|
||||
distances: &MappedInterner<Vec<u16>, QueryNode>,
|
||||
cost: u16,
|
||||
logger: &mut dyn SearchLogger<QueryGraph>,
|
||||
);
|
||||
|
@ -6,11 +6,10 @@ use std::iter::FromIterator;
|
||||
|
||||
use roaring::RoaringBitmap;
|
||||
|
||||
use super::{RankingRuleGraph, RankingRuleGraphTrait, DeadEndsCache};
|
||||
use super::{DeadEndsCache, RankingRuleGraph, RankingRuleGraphTrait};
|
||||
use crate::search::new::interner::{DedupInterner, Interned, MappedInterner};
|
||||
use crate::search::new::logger::SearchLogger;
|
||||
use crate::search::new::query_term::{Phrase, QueryTerm};
|
||||
use crate::search::new::small_bitmap::SmallBitmap;
|
||||
use crate::search::new::{QueryGraph, QueryNode, SearchContext};
|
||||
use crate::Result;
|
||||
|
||||
@ -66,13 +65,13 @@ impl RankingRuleGraphTrait for ProximityGraph {
|
||||
fn log_state(
|
||||
graph: &RankingRuleGraph<Self>,
|
||||
paths: &[Vec<Interned<ProximityCondition>>],
|
||||
dead_end_path_cache: &DeadEndsCache<Self::Condition>,
|
||||
dead_ends_cache: &DeadEndsCache<Self::Condition>,
|
||||
universe: &RoaringBitmap,
|
||||
distances: &MappedInterner<Vec<(u16, SmallBitmap<ProximityCondition>)>, QueryNode>,
|
||||
distances: &MappedInterner<Vec<u16>, QueryNode>,
|
||||
cost: u16,
|
||||
logger: &mut dyn SearchLogger<QueryGraph>,
|
||||
) {
|
||||
logger.log_proximity_state(graph, paths, dead_end_path_cache, universe, distances, cost);
|
||||
logger.log_proximity_state(graph, paths, dead_ends_cache, universe, distances, cost);
|
||||
}
|
||||
|
||||
fn label_for_condition<'ctx>(
|
||||
|
@ -5,7 +5,6 @@ use crate::search::new::interner::{DedupInterner, Interned, MappedInterner};
|
||||
use crate::search::new::logger::SearchLogger;
|
||||
use crate::search::new::query_graph::QueryNodeData;
|
||||
use crate::search::new::query_term::{LocatedQueryTerm, Phrase, QueryTerm};
|
||||
use crate::search::new::small_bitmap::SmallBitmap;
|
||||
use crate::search::new::{QueryGraph, QueryNode, SearchContext};
|
||||
use crate::Result;
|
||||
use std::collections::HashSet;
|
||||
@ -136,13 +135,13 @@ impl RankingRuleGraphTrait for TypoGraph {
|
||||
fn log_state(
|
||||
graph: &RankingRuleGraph<Self>,
|
||||
paths: &[Vec<Interned<TypoCondition>>],
|
||||
dead_end_path_cache: &DeadEndsCache<TypoCondition>,
|
||||
dead_ends_cache: &DeadEndsCache<TypoCondition>,
|
||||
universe: &RoaringBitmap,
|
||||
distances: &MappedInterner<Vec<(u16, SmallBitmap<TypoCondition>)>, QueryNode>,
|
||||
distances: &MappedInterner<Vec<u16>, QueryNode>,
|
||||
cost: u16,
|
||||
logger: &mut dyn SearchLogger<QueryGraph>,
|
||||
) {
|
||||
logger.log_typo_state(graph, paths, dead_end_path_cache, universe, distances, cost);
|
||||
logger.log_typo_state(graph, paths, dead_ends_cache, universe, distances, cost);
|
||||
}
|
||||
|
||||
fn label_for_condition<'ctx>(
|
||||
|
Reference in New Issue
Block a user