mirror of
https://github.com/meilisearch/MeiliSearch
synced 2025-07-03 11:57:07 +02:00
map: Allow using the Levenshtein algorithm to search
This commit is contained in:
parent
0581b296bb
commit
96d2fbcd3d
4 changed files with 78 additions and 6 deletions
|
@ -1,4 +1,6 @@
|
|||
extern crate env_logger;
|
||||
extern crate fst;
|
||||
extern crate fst_levenshtein;
|
||||
extern crate futures;
|
||||
extern crate raptor;
|
||||
extern crate tokio_minihttp;
|
||||
|
@ -8,6 +10,8 @@ extern crate url;
|
|||
|
||||
use std::io;
|
||||
|
||||
use fst_levenshtein::Levenshtein;
|
||||
use fst::{IntoStreamer, Streamer};
|
||||
use futures::future;
|
||||
use tokio_minihttp::{Request, Response, Http};
|
||||
use tokio_proto::TcpServer;
|
||||
|
@ -34,8 +38,18 @@ impl Service for MainService {
|
|||
|
||||
if let Some((_, key)) = url.query_pairs().find(|&(ref k, _)| k == "q") {
|
||||
let key = key.to_lowercase();
|
||||
let values = self.map.get(&key).map(|a| &a[..10]);
|
||||
resp.body(&format!("{:?}", values));
|
||||
|
||||
let lev = Levenshtein::new(&key, 2).unwrap();
|
||||
|
||||
let mut body = String::new();
|
||||
|
||||
let mut stream = self.map.search(lev).into_stream();
|
||||
while let Some((key, values)) = stream.next() {
|
||||
let values = &values[..values.len().min(10)];
|
||||
body.push_str(&format!("{:?} {:?}\n", key, values));
|
||||
}
|
||||
|
||||
resp.body(&body);
|
||||
}
|
||||
|
||||
future::ok(resp)
|
||||
|
|
40
src/lib.rs
40
src/lib.rs
|
@ -5,6 +5,7 @@ extern crate serde_json;
|
|||
#[macro_use] extern crate serde_derive;
|
||||
extern crate smallvec;
|
||||
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::io::Write;
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
|
@ -50,6 +51,45 @@ impl MultiMap {
|
|||
pub fn get<K: AsRef<[u8]>>(&self, key: K) -> Option<&[u64]> {
|
||||
self.map.get(key).map(|i| &*self.values[i as usize])
|
||||
}
|
||||
|
||||
pub fn search<A: fst::Automaton>(&self, aut: A) -> StreamBuilder<A> {
|
||||
StreamBuilder {
|
||||
inner: self.map.search(aut),
|
||||
values: &self.values,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StreamBuilder<'a, A: fst::Automaton> {
|
||||
inner: fst::map::StreamBuilder<'a, A>,
|
||||
values: &'a [SmallVec32<u64>],
|
||||
}
|
||||
|
||||
impl<'a, A: fst::Automaton> Deref for StreamBuilder<'a, A> {
|
||||
type Target = fst::map::StreamBuilder<'a, A>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, A: fst::Automaton> DerefMut for StreamBuilder<'a, A> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, A: fst::Automaton> fst::IntoStreamer<'a> for StreamBuilder<'a, A> {
|
||||
type Item = (&'a str, &'a [u64]);
|
||||
|
||||
type Into = Stream<'a, A>;
|
||||
|
||||
fn into_stream(self) -> Self::Into {
|
||||
Stream {
|
||||
inner: self.inner.into_stream(),
|
||||
values: self.values,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Stream<'a, A: fst::Automaton = fst::automaton::AlwaysMatch> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue