1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
use crate::simple::{indexable::Indexable, search_index::SearchIndex};
use std::clone::Clone;
use std::cmp::Ord;
// -----------------------------------------------------------------------------
impl<K: Clone + Ord> SearchIndex<K> {
// -------------------------------------------------------------------------
//
/// Removes a key-value pair from the search index.
///
/// Note that for the search results to be accurate, it is important to
/// update the search index as the collection is updated. If an element is
/// removed from your collection, it should also be removed from the search
/// index.
///
/// Basic usage:
///
/// ```rust
/// # use indicium::simple::{AutocompleteType, Indexable, SearchIndex, SearchType};
/// #
/// # struct MyStruct {
/// # title: String,
/// # year: u16,
/// # body: String,
/// # }
/// #
/// # impl Indexable for MyStruct {
/// # fn strings(&self) -> Vec<String> {
/// # vec![
/// # self.title.clone(),
/// # self.year.to_string(),
/// # self.body.clone(),
/// # ]
/// # }
/// # }
/// #
/// # let my_vec = vec![
/// # MyStruct {
/// # title: "Harold Godwinson".to_string(),
/// # year: 1066,
/// # body: "Last crowned Anglo-Saxon king of England.".to_string(),
/// # },
/// # MyStruct {
/// # title: "Edgar Ætheling".to_string(),
/// # year: 1066,
/// # body: "Last male member of the royal house of Cerdic of Wessex.".to_string(),
/// # },
/// # MyStruct {
/// # title: "William the Conqueror".to_string(),
/// # year: 1066,
/// # body: "First Norman monarch of England.".to_string(),
/// # },
/// # MyStruct {
/// # title: "William Rufus".to_string(),
/// # year: 1087,
/// # body: "Third son of William the Conqueror.".to_string(),
/// # },
/// # MyStruct {
/// # title: "Henry Beauclerc".to_string(),
/// # year: 1100,
/// # body: "Fourth son of William the Conqueror.".to_string(),
/// # },
/// # ];
/// #
/// # let mut search_index: SearchIndex<usize> = SearchIndex::default();
/// #
/// # my_vec
/// # .iter()
/// # .enumerate()
/// # .for_each(|(index, element)|
/// # search_index.insert(&index, element)
/// # );
/// #
/// let search_results = search_index.search("last");
/// assert_eq!(search_results, vec![&0, &1]);
///
/// search_index.remove(
/// &0,
/// &MyStruct {
/// title: "Harold Godwinson".to_string(),
/// year: 1066,
/// body: "Last crowned Anglo-Saxon king of England.".to_string(),
/// },
/// );
///
/// let search_results = search_index.search("last");
/// assert_eq!(search_results, vec![&1]);
/// ```
#[tracing::instrument(level = "trace", name = "Search Index Remove", skip(self, key, value))]
pub fn remove(&mut self, key: &K, value: &dyn Indexable) {
// Get all keywords for the `Indexable` record:
let keywords = self.indexable_keywords(value);
// Iterate over the keywords:
keywords
.iter()
// For each keyword, remove this record's _key_ from the _keyword
// entry_:
.for_each(|keyword| {
// Attempt to get mutuable reference to the _keyword entry_ in
// the search index:
let is_empty = if let Some(keys) = self.b_tree_map.get_mut(keyword) {
// If keyword found in search index, remove the _key
// reference_ for this record from _keyword entry_:
keys.remove(key);
// Return whether the _keyword entry_ is now empty or not:
keys.is_empty()
} else {
// If keyword not found in search index, signal that we
// should **not** remove the _keyword entry_ because that
// would result in an error:
false
}; // if
// If the _keyword entry_ no longer contains any _key
// references_, it is empty and we should remove the keyword
// from the search index:
if is_empty { self.b_tree_map.remove(keyword); }
}) // for_each
} // fn
} // impl