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 127 128 129 130 131 132 133
use crate::simple::{indexable::Indexable, search_index::SearchIndex};
use std::clone::Clone;
use std::cmp::Ord;
use std::collections::HashSet;
// -----------------------------------------------------------------------------
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 mut keywords: HashSet<String> = self.indexable_keywords(value);
// If `dump_keyword` feature is turned on, ensure that all records are
// detached from this special keyword:
if let Some(dump_keyword) = &self.dump_keyword {
keywords.insert(dump_keyword.to_string());
} // if
// 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