2018-12-10 22:13:25 +08:00
|
|
|
use std::path::{Path, PathBuf};
|
|
|
|
use std::error::Error;
|
2018-12-29 19:26:33 +08:00
|
|
|
use std::borrow::Cow;
|
|
|
|
use std::fs::File;
|
2018-12-10 22:13:25 +08:00
|
|
|
|
2018-12-29 19:26:33 +08:00
|
|
|
use hashbrown::HashMap;
|
2018-12-10 22:13:25 +08:00
|
|
|
use serde_derive::{Serialize, Deserialize};
|
|
|
|
use structopt::StructOpt;
|
|
|
|
|
2018-12-29 19:26:33 +08:00
|
|
|
use meilidb::database::{Database, Schema, UpdateBuilder};
|
2018-12-10 22:13:25 +08:00
|
|
|
use meilidb::tokenizer::DefaultBuilder;
|
|
|
|
|
|
|
|
#[derive(Debug, StructOpt)]
|
|
|
|
pub struct Opt {
|
2018-12-29 19:26:33 +08:00
|
|
|
/// The destination where the database must be created.
|
2018-12-10 22:13:25 +08:00
|
|
|
#[structopt(parse(from_os_str))]
|
|
|
|
pub database_path: PathBuf,
|
|
|
|
|
|
|
|
/// The csv file to index.
|
|
|
|
#[structopt(parse(from_os_str))]
|
|
|
|
pub csv_data_path: PathBuf,
|
|
|
|
|
2018-12-29 19:26:33 +08:00
|
|
|
/// The path to the schema.
|
|
|
|
#[structopt(long = "schema", parse(from_os_str))]
|
|
|
|
pub schema_path: PathBuf,
|
2018-12-10 22:13:25 +08:00
|
|
|
}
|
|
|
|
|
2018-12-29 19:26:33 +08:00
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
struct Document<'a> (
|
|
|
|
#[serde(borrow)]
|
|
|
|
HashMap<Cow<'a, str>, Cow<'a, str>>
|
|
|
|
);
|
2018-12-10 22:13:25 +08:00
|
|
|
|
|
|
|
fn index(schema: Schema, database_path: &Path, csv_data_path: &Path) -> Result<Database, Box<Error>> {
|
|
|
|
let database = Database::create(database_path, schema.clone())?;
|
|
|
|
|
|
|
|
println!("start indexing...");
|
|
|
|
|
|
|
|
let tokenizer_builder = DefaultBuilder::new();
|
|
|
|
let update_path = tempfile::NamedTempFile::new()?;
|
2018-12-30 23:17:18 +08:00
|
|
|
let mut update = UpdateBuilder::new(update_path.path().to_path_buf(), schema);
|
2018-12-10 22:13:25 +08:00
|
|
|
|
|
|
|
let mut rdr = csv::Reader::from_path(csv_data_path)?;
|
|
|
|
let mut raw_record = csv::StringRecord::new();
|
|
|
|
let headers = rdr.headers()?.clone();
|
|
|
|
|
|
|
|
while rdr.read_record(&mut raw_record)? {
|
|
|
|
let document: Document = match raw_record.deserialize(Some(&headers)) {
|
|
|
|
Ok(document) => document,
|
|
|
|
Err(e) => {
|
|
|
|
eprintln!("{:?}", e);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-01-01 01:33:59 +08:00
|
|
|
update.update_document(&document, &tokenizer_builder)?;
|
2018-12-10 22:13:25 +08:00
|
|
|
}
|
|
|
|
|
2019-01-01 01:33:59 +08:00
|
|
|
let update = update.build()?;
|
2018-12-10 22:13:25 +08:00
|
|
|
database.ingest_update_file(update)?;
|
|
|
|
|
|
|
|
Ok(database)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn main() -> Result<(), Box<Error>> {
|
|
|
|
let opt = Opt::from_args();
|
|
|
|
|
2018-12-29 19:26:33 +08:00
|
|
|
let schema = {
|
|
|
|
let file = File::open(&opt.schema_path)?;
|
|
|
|
Schema::from_toml(file)?
|
|
|
|
};
|
2018-12-10 22:13:25 +08:00
|
|
|
|
|
|
|
let (elapsed, result) = elapsed::measure_time(|| {
|
|
|
|
index(schema, &opt.database_path, &opt.csv_data_path)
|
|
|
|
});
|
|
|
|
|
2018-12-11 19:06:02 +08:00
|
|
|
if let Err(e) = result {
|
|
|
|
return Err(e.into())
|
|
|
|
}
|
2018-12-10 22:13:25 +08:00
|
|
|
|
|
|
|
println!("database created in {} at: {:?}", elapsed, opt.database_path);
|
|
|
|
Ok(())
|
|
|
|
}
|