rename identifier into primaryKey; fix #514

This commit is contained in:
qdequele 2020-03-09 18:40:49 +01:00
parent 8ffa80883a
commit c984d8d5a5
No known key found for this signature in database
GPG Key ID: B3F0A000EBF11745
24 changed files with 142 additions and 142 deletions

View File

@ -1,5 +1,5 @@
{ {
"identifier": "id", "primaryKey": "id",
"searchableAttributes": ["title", "overview"], "searchableAttributes": ["title", "overview"],
"displayedAttributes": [ "displayedAttributes": [
"id", "id",

View File

@ -380,7 +380,7 @@ mod tests {
database.set_update_callback(Box::new(update_fn)); database.set_update_callback(Box::new(update_fn));
let settings_update = SettingsUpdate{ let settings_update = SettingsUpdate{
identifier: UpdateState::Update("id".to_string()), primary_key: UpdateState::Update("id".to_string()),
..SettingsUpdate::default() ..SettingsUpdate::default()
}; };
@ -451,7 +451,7 @@ mod tests {
database.set_update_callback(Box::new(update_fn)); database.set_update_callback(Box::new(update_fn));
let settings_update = SettingsUpdate{ let settings_update = SettingsUpdate{
identifier: UpdateState::Update("id".to_string()), primary_key: UpdateState::Update("id".to_string()),
..SettingsUpdate::default() ..SettingsUpdate::default()
}; };
@ -521,7 +521,7 @@ mod tests {
database.set_update_callback(Box::new(update_fn)); database.set_update_callback(Box::new(update_fn));
let settings_update = SettingsUpdate{ let settings_update = SettingsUpdate{
identifier: UpdateState::Update("id".to_string()), primary_key: UpdateState::Update("id".to_string()),
..SettingsUpdate::default() ..SettingsUpdate::default()
}; };
@ -584,7 +584,7 @@ mod tests {
database.set_update_callback(Box::new(update_fn)); database.set_update_callback(Box::new(update_fn));
let settings_update = SettingsUpdate{ let settings_update = SettingsUpdate{
identifier: UpdateState::Update("id".to_string()), primary_key: UpdateState::Update("id".to_string()),
..SettingsUpdate::default() ..SettingsUpdate::default()
}; };
@ -736,7 +736,7 @@ mod tests {
database.set_update_callback(Box::new(update_fn)); database.set_update_callback(Box::new(update_fn));
let settings_update = SettingsUpdate{ let settings_update = SettingsUpdate{
identifier: UpdateState::Update("id".to_string()), primary_key: UpdateState::Update("id".to_string()),
..SettingsUpdate::default() ..SettingsUpdate::default()
}; };
@ -824,7 +824,7 @@ mod tests {
database.set_update_callback(Box::new(update_fn)); database.set_update_callback(Box::new(update_fn));
let settings_update = SettingsUpdate{ let settings_update = SettingsUpdate{
identifier: UpdateState::Update("id".to_string()), primary_key: UpdateState::Update("id".to_string()),
..SettingsUpdate::default() ..SettingsUpdate::default()
}; };
@ -971,7 +971,7 @@ mod tests {
database.set_update_callback(Box::new(update_fn)); database.set_update_callback(Box::new(update_fn));
let settings_update = SettingsUpdate{ let settings_update = SettingsUpdate{
identifier: UpdateState::Update("id".to_string()), primary_key: UpdateState::Update("id".to_string()),
..SettingsUpdate::default() ..SettingsUpdate::default()
}; };
@ -1046,7 +1046,7 @@ mod tests {
database.set_update_callback(Box::new(update_fn)); database.set_update_callback(Box::new(update_fn));
let settings_update = SettingsUpdate{ let settings_update = SettingsUpdate{
identifier: UpdateState::Update("id".to_string()), primary_key: UpdateState::Update("id".to_string()),
..SettingsUpdate::default() ..SettingsUpdate::default()
}; };

View File

@ -12,7 +12,7 @@ pub type MResult<T> = Result<T, Error>;
pub enum Error { pub enum Error {
Io(io::Error), Io(io::Error),
IndexAlreadyExists, IndexAlreadyExists,
MissingIdentifier, MissingPrimaryKey,
SchemaMissing, SchemaMissing,
WordIndexMissing, WordIndexMissing,
MissingDocumentId, MissingDocumentId,
@ -87,7 +87,7 @@ impl fmt::Display for Error {
match self { match self {
Io(e) => write!(f, "{}", e), Io(e) => write!(f, "{}", e),
IndexAlreadyExists => write!(f, "index already exists"), IndexAlreadyExists => write!(f, "index already exists"),
MissingIdentifier => write!(f, "schema cannot be built without identifier"), MissingPrimaryKey => write!(f, "schema cannot be built without primary key"),
SchemaMissing => write!(f, "this index does not have a schema"), SchemaMissing => write!(f, "this index does not have a schema"),
WordIndexMissing => write!(f, "this index does not have a word index"), WordIndexMissing => write!(f, "this index does not have a word index"),
MissingDocumentId => write!(f, "document id is missing"), MissingDocumentId => write!(f, "document id is missing"),
@ -109,7 +109,7 @@ impl error::Error for Error {}
#[derive(Debug)] #[derive(Debug)]
pub enum UnsupportedOperation { pub enum UnsupportedOperation {
SchemaAlreadyExists, SchemaAlreadyExists,
CannotUpdateSchemaIdentifier, CannotUpdateSchemaPrimaryKey,
CannotReorderSchemaAttribute, CannotReorderSchemaAttribute,
CanOnlyIntroduceNewSchemaAttributesAtEnd, CanOnlyIntroduceNewSchemaAttributesAtEnd,
CannotRemoveSchemaAttribute, CannotRemoveSchemaAttribute,
@ -120,7 +120,7 @@ impl fmt::Display for UnsupportedOperation {
use self::UnsupportedOperation::*; use self::UnsupportedOperation::*;
match self { match self {
SchemaAlreadyExists => write!(f, "Cannot update index which already have a schema"), SchemaAlreadyExists => write!(f, "Cannot update index which already have a schema"),
CannotUpdateSchemaIdentifier => write!(f, "Cannot update the identifier of a schema"), CannotUpdateSchemaPrimaryKey => write!(f, "Cannot update the primary key of a schema"),
CannotReorderSchemaAttribute => write!(f, "Cannot reorder the attributes of a schema"), CannotReorderSchemaAttribute => write!(f, "Cannot reorder the attributes of a schema"),
CanOnlyIntroduceNewSchemaAttributesAtEnd => { CanOnlyIntroduceNewSchemaAttributesAtEnd => {
write!(f, "Can only introduce new attributes at end of a schema") write!(f, "Can only introduce new attributes at end of a schema")

View File

@ -259,7 +259,7 @@ mod tests {
let mut postings_lists = HashMap::new(); let mut postings_lists = HashMap::new();
let mut fields_counts = HashMap::<_, u16>::new(); let mut fields_counts = HashMap::<_, u16>::new();
let mut schema = Schema::with_identifier("id"); let mut schema = Schema::with_primary_key("id");
for (word, indexes) in iter { for (word, indexes) in iter {
let mut final_indexes = Vec::new(); let mut final_indexes = Vec::new();

View File

@ -8,13 +8,13 @@ use siphasher::sip::SipHasher;
use super::{ConvertToString, SerializerError}; use super::{ConvertToString, SerializerError};
pub fn extract_document_id<D>( pub fn extract_document_id<D>(
identifier: &str, primary_key: &str,
document: &D, document: &D,
) -> Result<Option<DocumentId>, SerializerError> ) -> Result<Option<DocumentId>, SerializerError>
where where
D: serde::Serialize, D: serde::Serialize,
{ {
let serializer = ExtractDocumentId { identifier }; let serializer = ExtractDocumentId { primary_key };
document.serialize(serializer) document.serialize(serializer)
} }
@ -52,7 +52,7 @@ pub fn compute_document_id<H: Hash>(t: H) -> DocumentId {
} }
struct ExtractDocumentId<'a> { struct ExtractDocumentId<'a> {
identifier: &'a str, primary_key: &'a str,
} }
impl<'a> ser::Serializer for ExtractDocumentId<'a> { impl<'a> ser::Serializer for ExtractDocumentId<'a> {
@ -188,7 +188,7 @@ impl<'a> ser::Serializer for ExtractDocumentId<'a> {
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
let serializer = ExtractDocumentIdMapSerializer { let serializer = ExtractDocumentIdMapSerializer {
identifier: self.identifier, primary_key: self.primary_key,
document_id: None, document_id: None,
current_key_name: None, current_key_name: None,
}; };
@ -202,7 +202,7 @@ impl<'a> ser::Serializer for ExtractDocumentId<'a> {
_len: usize, _len: usize,
) -> Result<Self::SerializeStruct, Self::Error> { ) -> Result<Self::SerializeStruct, Self::Error> {
let serializer = ExtractDocumentIdStructSerializer { let serializer = ExtractDocumentIdStructSerializer {
identifier: self.identifier, primary_key: self.primary_key,
document_id: None, document_id: None,
}; };
@ -223,7 +223,7 @@ impl<'a> ser::Serializer for ExtractDocumentId<'a> {
} }
pub struct ExtractDocumentIdMapSerializer<'a> { pub struct ExtractDocumentIdMapSerializer<'a> {
identifier: &'a str, primary_key: &'a str,
document_id: Option<DocumentId>, document_id: Option<DocumentId>,
current_key_name: Option<String>, current_key_name: Option<String>,
} }
@ -260,7 +260,7 @@ impl<'a> ser::SerializeMap for ExtractDocumentIdMapSerializer<'a> {
{ {
let key = key.serialize(ConvertToString)?; let key = key.serialize(ConvertToString)?;
if self.identifier == key { if self.primary_key == key {
let value = serde_json::to_string(value).and_then(|s| serde_json::from_str(&s))?; let value = serde_json::to_string(value).and_then(|s| serde_json::from_str(&s))?;
match value_to_string(&value).map(|s| compute_document_id(&s)) { match value_to_string(&value).map(|s| compute_document_id(&s)) {
Some(document_id) => self.document_id = Some(document_id), Some(document_id) => self.document_id = Some(document_id),
@ -277,7 +277,7 @@ impl<'a> ser::SerializeMap for ExtractDocumentIdMapSerializer<'a> {
} }
pub struct ExtractDocumentIdStructSerializer<'a> { pub struct ExtractDocumentIdStructSerializer<'a> {
identifier: &'a str, primary_key: &'a str,
document_id: Option<DocumentId>, document_id: Option<DocumentId>,
} }
@ -293,7 +293,7 @@ impl<'a> ser::SerializeStruct for ExtractDocumentIdStructSerializer<'a> {
where where
T: Serialize, T: Serialize,
{ {
if self.identifier == key { if self.primary_key == key {
let value = serde_json::to_string(value).and_then(|s| serde_json::from_str(&s))?; let value = serde_json::to_string(value).and_then(|s| serde_json::from_str(&s))?;
match value_to_string(&value).map(compute_document_id) { match value_to_string(&value).map(compute_document_id) {
Some(document_id) => self.document_id = Some(document_id), Some(document_id) => self.document_id = Some(document_id),

View File

@ -57,7 +57,7 @@ impl fmt::Display for SerializerError {
f.write_str("serialized document does not have an id according to the schema") f.write_str("serialized document does not have an id according to the schema")
} }
SerializerError::InvalidDocumentIdType => { SerializerError::InvalidDocumentIdType => {
f.write_str("documents identifiers can be of type integer or string only composed of alphanumeric characters, hyphens (-) and underscores (_).") f.write_str("documents primary keys can be of type integer or string only composed of alphanumeric characters, hyphens (-) and underscores (_).")
} }
SerializerError::Zlmdb(e) => write!(f, "heed related error: {}", e), SerializerError::Zlmdb(e) => write!(f, "heed related error: {}", e),
SerializerError::SerdeJson(e) => write!(f, "serde json error: {}", e), SerializerError::SerdeJson(e) => write!(f, "serde json error: {}", e),

View File

@ -54,7 +54,7 @@ impl Settings {
Ok(SettingsUpdate { Ok(SettingsUpdate {
ranking_rules, ranking_rules,
distinct_attribute: settings.distinct_attribute.into(), distinct_attribute: settings.distinct_attribute.into(),
identifier: UpdateState::Nothing, primary_key: UpdateState::Nothing,
searchable_attributes: settings.searchable_attributes.into(), searchable_attributes: settings.searchable_attributes.into(),
displayed_attributes: settings.displayed_attributes.into(), displayed_attributes: settings.displayed_attributes.into(),
stop_words: settings.stop_words.into(), stop_words: settings.stop_words.into(),
@ -160,7 +160,7 @@ impl RankingRule {
pub struct SettingsUpdate { pub struct SettingsUpdate {
pub ranking_rules: UpdateState<Vec<RankingRule>>, pub ranking_rules: UpdateState<Vec<RankingRule>>,
pub distinct_attribute: UpdateState<String>, pub distinct_attribute: UpdateState<String>,
pub identifier: UpdateState<String>, pub primary_key: UpdateState<String>,
pub searchable_attributes: UpdateState<Vec<String>>, pub searchable_attributes: UpdateState<Vec<String>>,
pub displayed_attributes: UpdateState<HashSet<String>>, pub displayed_attributes: UpdateState<HashSet<String>>,
pub stop_words: UpdateState<BTreeSet<String>>, pub stop_words: UpdateState<BTreeSet<String>>,
@ -173,7 +173,7 @@ impl Default for SettingsUpdate {
Self { Self {
ranking_rules: UpdateState::Nothing, ranking_rules: UpdateState::Nothing,
distinct_attribute: UpdateState::Nothing, distinct_attribute: UpdateState::Nothing,
identifier: UpdateState::Nothing, primary_key: UpdateState::Nothing,
searchable_attributes: UpdateState::Nothing, searchable_attributes: UpdateState::Nothing,
displayed_attributes: UpdateState::Nothing, displayed_attributes: UpdateState::Nothing,
stop_words: UpdateState::Nothing, stop_words: UpdateState::Nothing,

View File

@ -115,11 +115,11 @@ pub fn apply_documents_addition<'a, 'b>(
None => return Err(Error::SchemaMissing), None => return Err(Error::SchemaMissing),
}; };
let identifier = schema.identifier().ok_or(Error::MissingIdentifier)?; let primary_key = schema.primary_key().ok_or(Error::MissingPrimaryKey)?;
// 1. store documents ids for future deletion // 1. store documents ids for future deletion
for document in addition { for document in addition {
let document_id = match extract_document_id(&identifier, &document)? { let document_id = match extract_document_id(&primary_key, &document)? {
Some(id) => id, Some(id) => id,
None => return Err(Error::MissingDocumentId), None => return Err(Error::MissingDocumentId),
}; };
@ -184,11 +184,11 @@ pub fn apply_documents_partial_addition<'a, 'b>(
None => return Err(Error::SchemaMissing), None => return Err(Error::SchemaMissing),
}; };
let identifier = schema.identifier().ok_or(Error::MissingIdentifier)?; let primary_key = schema.primary_key().ok_or(Error::MissingPrimaryKey)?;
// 1. store documents ids for future deletion // 1. store documents ids for future deletion
for mut document in addition { for mut document in addition {
let document_id = match extract_document_id(&identifier, &document)? { let document_id = match extract_document_id(&primary_key, &document)? {
Some(id) => id, Some(id) => id,
None => return Err(Error::MissingDocumentId), None => return Err(Error::MissingDocumentId),
}; };

View File

@ -40,8 +40,8 @@ impl DocumentsDeletion {
where where
D: serde::Serialize, D: serde::Serialize,
{ {
let identifier = schema.identifier().ok_or(Error::MissingIdentifier)?; let primary_key = schema.primary_key().ok_or(Error::MissingPrimaryKey)?;
let document_id = match extract_document_id(&identifier, &document)? { let document_id = match extract_document_id(&primary_key, &document)? {
Some(id) => id, Some(id) => id,
None => return Err(Error::MissingDocumentId), None => return Err(Error::MissingDocumentId),
}; };

View File

@ -35,9 +35,9 @@ pub fn apply_settings_update(
let mut schema = match index.main.schema(writer)? { let mut schema = match index.main.schema(writer)? {
Some(schema) => schema, Some(schema) => schema,
None => { None => {
match settings.identifier.clone() { match settings.primary_key.clone() {
UpdateState::Update(id) => Schema::with_identifier(&id), UpdateState::Update(id) => Schema::with_primary_key(&id),
_ => return Err(Error::MissingIdentifier) _ => return Err(Error::MissingPrimaryKey)
} }
} }
}; };

View File

@ -13,7 +13,7 @@ pub trait RequestExt {
fn is_allowed(&self, acl: ACL) -> SResult<()>; fn is_allowed(&self, acl: ACL) -> SResult<()>;
fn url_param(&self, name: &str) -> SResult<String>; fn url_param(&self, name: &str) -> SResult<String>;
fn index(&self) -> SResult<Index>; fn index(&self) -> SResult<Index>;
fn identifier(&self) -> SResult<String>; fn document_id(&self) -> SResult<String>;
} }
impl RequestExt for Request<Data> { impl RequestExt for Request<Data> {
@ -55,7 +55,7 @@ impl RequestExt for Request<Data> {
fn url_param(&self, name: &str) -> SResult<String> { fn url_param(&self, name: &str) -> SResult<String> {
let param = self let param = self
.param::<String>(name) .param::<String>(name)
.map_err(|_| ResponseError::bad_parameter("identifier", name))?; .map_err(|e| ResponseError::bad_parameter(name, e))?;
Ok(param) Ok(param)
} }
@ -69,10 +69,10 @@ impl RequestExt for Request<Data> {
Ok(index) Ok(index)
} }
fn identifier(&self) -> SResult<String> { fn document_id(&self) -> SResult<String> {
let name = self let name = self
.param::<String>("identifier") .param::<String>("documentId")
.map_err(|_| ResponseError::bad_parameter("identifier", "identifier"))?; .map_err(|_| ResponseError::bad_parameter("documentId", "primaryKey"))?;
Ok(name) Ok(name)
} }

View File

@ -15,18 +15,18 @@ pub async fn get_document(ctx: Request<Data>) -> SResult<Response> {
let index = ctx.index()?; let index = ctx.index()?;
let identifier = ctx.identifier()?; let original_document_id = ctx.document_id()?;
let document_id = meilisearch_core::serde::compute_document_id(identifier.clone()); let document_id = meilisearch_core::serde::compute_document_id(original_document_id.clone());
let db = &ctx.state().db; let db = &ctx.state().db;
let reader = db.main_read_txn()?; let reader = db.main_read_txn()?;
let response = index let response = index
.document::<IndexMap<String, Value>>(&reader, None, document_id)? .document::<IndexMap<String, Value>>(&reader, None, document_id)?
.ok_or(ResponseError::document_not_found(&identifier))?; .ok_or(ResponseError::document_not_found(&original_document_id))?;
if response.is_empty() { if response.is_empty() {
return Err(ResponseError::document_not_found(identifier)); return Err(ResponseError::document_not_found(&original_document_id));
} }
Ok(tide::Response::new(200).body_json(&response)?) Ok(tide::Response::new(200).body_json(&response)?)
@ -42,8 +42,8 @@ pub async fn delete_document(ctx: Request<Data>) -> SResult<Response> {
ctx.is_allowed(Private)?; ctx.is_allowed(Private)?;
let index = ctx.index()?; let index = ctx.index()?;
let identifier = ctx.identifier()?; let document_id = ctx.document_id()?;
let document_id = meilisearch_core::serde::compute_document_id(identifier); let document_id = meilisearch_core::serde::compute_document_id(document_id);
let db = &ctx.state().db; let db = &ctx.state().db;
let mut update_writer = db.update_write_txn()?; let mut update_writer = db.update_write_txn()?;
let mut documents_deletion = index.documents_deletion(); let mut documents_deletion = index.documents_deletion();
@ -108,7 +108,7 @@ pub async fn get_all_documents(ctx: Request<Data>) -> SResult<Response> {
Ok(tide::Response::new(200).body_json(&response_body)?) Ok(tide::Response::new(200).body_json(&response_body)?)
} }
fn find_identifier(document: &IndexMap<String, Value>) -> Option<String> { fn find_primary_key(document: &IndexMap<String, Value>) -> Option<String> {
for key in document.keys() { for key in document.keys() {
if key.to_lowercase().contains("id") { if key.to_lowercase().contains("id") {
return Some(key.to_string()); return Some(key.to_string());
@ -120,7 +120,7 @@ fn find_identifier(document: &IndexMap<String, Value>) -> Option<String> {
#[derive(Default, Deserialize)] #[derive(Default, Deserialize)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
struct UpdateDocumentsQuery { struct UpdateDocumentsQuery {
identifier: Option<String>, document_id: Option<String>,
} }
async fn update_multiple_documents(mut ctx: Request<Data>, is_partial: bool) -> SResult<Response> { async fn update_multiple_documents(mut ctx: Request<Data>, is_partial: bool) -> SResult<Response> {
@ -137,16 +137,16 @@ async fn update_multiple_documents(mut ctx: Request<Data>, is_partial: bool) ->
let reader = db.main_read_txn()?; let reader = db.main_read_txn()?;
let mut schema = index.main.schema(&reader)?.ok_or(ResponseError::internal("schema not found"))?; let mut schema = index.main.schema(&reader)?.ok_or(ResponseError::internal("schema not found"))?;
if schema.identifier().is_none() { if schema.primary_key().is_none() {
let id = match query.identifier { let id = match query.document_id {
Some(id) => id, Some(id) => id,
None => match data.first().and_then(|docs| find_identifier(docs)) { None => match data.first().and_then(|docs| find_primary_key(docs)) {
Some(id) => id, Some(id) => id,
None => return Err(ResponseError::bad_request("Could not infer a schema")), None => return Err(ResponseError::bad_request("Could not infer a schema")),
}, },
}; };
if schema.set_identifier(&id).is_ok() { if schema.set_primary_key(&id).is_ok() {
let mut writer = db.main_write_txn()?; let mut writer = db.main_write_txn()?;
index.main.put_schema(&mut writer, &schema)?; index.main.put_schema(&mut writer, &schema)?;
writer.commit()?; writer.commit()?;
@ -190,10 +190,10 @@ pub async fn delete_multiple_documents(mut ctx: Request<Data>) -> SResult<Respon
let mut documents_deletion = index.documents_deletion(); let mut documents_deletion = index.documents_deletion();
for identifier in data { for document_id in data {
if let Some(identifier) = meilisearch_core::serde::value_to_string(&identifier) { if let Some(document_id) = meilisearch_core::serde::value_to_string(&document_id) {
documents_deletion documents_deletion
.delete_document_by_id(meilisearch_core::serde::compute_document_id(identifier)); .delete_document_by_id(meilisearch_core::serde::compute_document_id(document_id));
} }
} }

View File

@ -39,9 +39,9 @@ pub async fn list_indexes(ctx: Request<Data>) -> SResult<Response> {
let created_at = index.main.created_at(&reader)?.into_internal_error()?; let created_at = index.main.created_at(&reader)?.into_internal_error()?;
let updated_at = index.main.updated_at(&reader)?.into_internal_error()?; let updated_at = index.main.updated_at(&reader)?.into_internal_error()?;
let identifier = match index.main.schema(&reader) { let primary_key = match index.main.schema(&reader) {
Ok(Some(schema)) => match schema.identifier() { Ok(Some(schema)) => match schema.primary_key() {
Some(identifier) => Some(identifier.to_owned()), Some(primary_key) => Some(primary_key.to_owned()),
None => None None => None
}, },
_ => None, _ => None,
@ -52,7 +52,7 @@ pub async fn list_indexes(ctx: Request<Data>) -> SResult<Response> {
uid: index_uid, uid: index_uid,
created_at, created_at,
updated_at, updated_at,
identifier, primary_key,
}; };
response_body.push(index_response); response_body.push(index_response);
} }
@ -73,7 +73,7 @@ struct IndexResponse {
uid: String, uid: String,
created_at: DateTime<Utc>, created_at: DateTime<Utc>,
updated_at: DateTime<Utc>, updated_at: DateTime<Utc>,
identifier: Option<String>, primary_key: Option<String>,
} }
pub async fn get_index(ctx: Request<Data>) -> SResult<Response> { pub async fn get_index(ctx: Request<Data>) -> SResult<Response> {
@ -89,9 +89,9 @@ pub async fn get_index(ctx: Request<Data>) -> SResult<Response> {
let created_at = index.main.created_at(&reader)?.into_internal_error()?; let created_at = index.main.created_at(&reader)?.into_internal_error()?;
let updated_at = index.main.updated_at(&reader)?.into_internal_error()?; let updated_at = index.main.updated_at(&reader)?.into_internal_error()?;
let identifier = match index.main.schema(&reader) { let primary_key = match index.main.schema(&reader) {
Ok(Some(schema)) => match schema.identifier() { Ok(Some(schema)) => match schema.primary_key() {
Some(identifier) => Some(identifier.to_owned()), Some(primary_key) => Some(primary_key.to_owned()),
None => None None => None
}, },
_ => None, _ => None,
@ -102,7 +102,7 @@ pub async fn get_index(ctx: Request<Data>) -> SResult<Response> {
uid, uid,
created_at, created_at,
updated_at, updated_at,
identifier, primary_key,
}; };
Ok(tide::Response::new(200).body_json(&response_body)?) Ok(tide::Response::new(200).body_json(&response_body)?)
@ -113,7 +113,7 @@ pub async fn get_index(ctx: Request<Data>) -> SResult<Response> {
struct IndexCreateRequest { struct IndexCreateRequest {
name: Option<String>, name: Option<String>,
uid: Option<String>, uid: Option<String>,
identifier: Option<String>, primary_key: Option<String>,
} }
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
@ -123,7 +123,7 @@ struct IndexCreateResponse {
uid: String, uid: String,
created_at: DateTime<Utc>, created_at: DateTime<Utc>,
updated_at: DateTime<Utc>, updated_at: DateTime<Utc>,
identifier: Option<String>, primary_key: Option<String>,
} }
pub async fn create_index(mut ctx: Request<Data>) -> SResult<Response> { pub async fn create_index(mut ctx: Request<Data>) -> SResult<Response> {
@ -175,9 +175,9 @@ pub async fn create_index(mut ctx: Request<Data>) -> SResult<Response> {
.updated_at(&writer)? .updated_at(&writer)?
.into_internal_error()?; .into_internal_error()?;
if let Some(id) = body.identifier.clone() { if let Some(id) = body.primary_key.clone() {
if let Some(mut schema) = created_index.main.schema(&mut writer)? { if let Some(mut schema) = created_index.main.schema(&mut writer)? {
if let Ok(_) = schema.set_identifier(&id) { if let Ok(_) = schema.set_primary_key(&id) {
created_index.main.put_schema(&mut writer, &schema)?; created_index.main.put_schema(&mut writer, &schema)?;
} }
} }
@ -190,7 +190,7 @@ pub async fn create_index(mut ctx: Request<Data>) -> SResult<Response> {
uid, uid,
created_at, created_at,
updated_at, updated_at,
identifier: body.identifier, primary_key: body.primary_key,
}; };
Ok(tide::Response::new(201).body_json(&response_body)?) Ok(tide::Response::new(201).body_json(&response_body)?)
@ -200,7 +200,7 @@ pub async fn create_index(mut ctx: Request<Data>) -> SResult<Response> {
#[serde(rename_all = "camelCase", deny_unknown_fields)] #[serde(rename_all = "camelCase", deny_unknown_fields)]
struct UpdateIndexRequest { struct UpdateIndexRequest {
name: Option<String>, name: Option<String>,
identifier: Option<String>, primary_key: Option<String>,
} }
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
@ -210,7 +210,7 @@ struct UpdateIndexResponse {
uid: String, uid: String,
created_at: DateTime<Utc>, created_at: DateTime<Utc>,
updated_at: DateTime<Utc>, updated_at: DateTime<Utc>,
identifier: Option<String>, primary_key: Option<String>,
} }
pub async fn update_index(mut ctx: Request<Data>) -> SResult<Response> { pub async fn update_index(mut ctx: Request<Data>) -> SResult<Response> {
@ -231,14 +231,14 @@ pub async fn update_index(mut ctx: Request<Data>) -> SResult<Response> {
index.main.put_name(&mut writer, &name)?; index.main.put_name(&mut writer, &name)?;
} }
if let Some(id) = body.identifier.clone() { if let Some(id) = body.primary_key.clone() {
if let Some(mut schema) = index.main.schema(&mut writer)? { if let Some(mut schema) = index.main.schema(&mut writer)? {
match schema.identifier() { match schema.primary_key() {
Some(_) => { Some(_) => {
return Err(ResponseError::bad_request("The index identifier cannot be updated")); return Err(ResponseError::bad_request("The index primary key cannot be updated"));
}, },
None => { None => {
if let Ok(_) = schema.set_identifier(&id) { if let Ok(_) = schema.set_primary_key(&id) {
index.main.put_schema(&mut writer, &schema)?; index.main.put_schema(&mut writer, &schema)?;
} }
} }
@ -254,11 +254,11 @@ pub async fn update_index(mut ctx: Request<Data>) -> SResult<Response> {
let created_at = index.main.created_at(&reader)?.into_internal_error()?; let created_at = index.main.created_at(&reader)?.into_internal_error()?;
let updated_at = index.main.updated_at(&reader)?.into_internal_error()?; let updated_at = index.main.updated_at(&reader)?.into_internal_error()?;
let identifier = match index.main.schema(&reader) { let primary_key = match index.main.schema(&reader) {
Ok(Some(schema)) => { Ok(Some(schema)) => {
match schema.identifier() { match schema.primary_key() {
Some(identifier) => { Some(primary_key) => {
Some(identifier.to_owned()) Some(primary_key.to_owned())
}, },
None => None None => None
} }
@ -272,7 +272,7 @@ pub async fn update_index(mut ctx: Request<Data>) -> SResult<Response> {
uid: index_uid, uid: index_uid,
created_at, created_at,
updated_at, updated_at,
identifier, primary_key,
}; };
Ok(tide::Response::new(200).body_json(&response_body)?) Ok(tide::Response::new(200).body_json(&response_body)?)

View File

@ -61,7 +61,7 @@ pub fn load_routes(app: &mut tide::Server<Data>) {
.put(|ctx| into_response(document::add_or_update_multiple_documents(ctx))) .put(|ctx| into_response(document::add_or_update_multiple_documents(ctx)))
.delete(|ctx| into_response(document::clear_all_documents(ctx))); .delete(|ctx| into_response(document::clear_all_documents(ctx)));
app.at("/indexes/:index/documents/:identifier") app.at("/indexes/:index/documents/:document_id")
.get(|ctx| into_response(document::get_document(ctx))) .get(|ctx| into_response(document::get_document(ctx)))
.delete(|ctx| into_response(document::delete_document(ctx))); .delete(|ctx| into_response(document::delete_document(ctx)));

View File

@ -81,7 +81,7 @@ pub async fn get_all(ctx: Request<Data>) -> SResult<Response> {
pub struct UpdateSettings { pub struct UpdateSettings {
pub ranking_rules: Option<Vec<String>>, pub ranking_rules: Option<Vec<String>>,
pub distinct_attribute: Option<String>, pub distinct_attribute: Option<String>,
pub identifier: Option<String>, pub primary_key: Option<String>,
pub searchable_attributes: Option<Vec<String>>, pub searchable_attributes: Option<Vec<String>>,
pub displayed_attributes: Option<HashSet<String>>, pub displayed_attributes: Option<HashSet<String>>,
pub stop_words: Option<BTreeSet<String>>, pub stop_words: Option<BTreeSet<String>>,
@ -124,7 +124,7 @@ pub async fn delete_all(ctx: Request<Data>) -> SResult<Response> {
let settings = SettingsUpdate { let settings = SettingsUpdate {
ranking_rules: UpdateState::Clear, ranking_rules: UpdateState::Clear,
distinct_attribute: UpdateState::Clear, distinct_attribute: UpdateState::Clear,
identifier: UpdateState::Clear, primary_key: UpdateState::Clear,
searchable_attributes: UpdateState::Clear, searchable_attributes: UpdateState::Clear,
displayed_attributes: UpdateState::Clear, displayed_attributes: UpdateState::Clear,
stop_words: UpdateState::Clear, stop_words: UpdateState::Clear,

View File

@ -285,8 +285,8 @@ impl Server {
self.delete_request_async(&url) self.delete_request_async(&url)
} }
pub fn get_identifier(&mut self) -> (Value, StatusCode) { pub fn get_primary_key(&mut self) -> (Value, StatusCode) {
let url = format!("/indexes/{}/settings/identifier", self.uid); let url = format!("/indexes/{}/settings/primary_key", self.uid);
self.get_request(&url) self.get_request(&url)
} }
@ -394,7 +394,7 @@ impl Server {
pub fn populate_movies(&mut self) { pub fn populate_movies(&mut self) {
let body = json!({ let body = json!({
"uid": "movies", "uid": "movies",
"identifier": "id", "primaryKey": "id",
}); });
self.create_index(body); self.create_index(body);

View File

@ -417,14 +417,14 @@ fn create_index_failed() {
// Resolve issue https://github.com/meilisearch/MeiliSearch/issues/492 // Resolve issue https://github.com/meilisearch/MeiliSearch/issues/492
#[test] #[test]
fn create_index_with_identifier_and_index() { fn create_index_with_primary_key_and_index() {
let mut server = common::Server::with_uid("movies"); let mut server = common::Server::with_uid("movies");
// 1 - Create the index // 1 - Create the index
let body = json!({ let body = json!({
"uid": "movies", "uid": "movies",
"identifier": "id", "primaryKey": "id",
}); });
let (_response, status_code) = server.create_index(body); let (_response, status_code) = server.create_index(body);
@ -512,84 +512,84 @@ fn create_index_with_invalid_uid() {
assert_eq!(message, "Index must have a valid uid; Index uid can be of type integer or string only composed of alphanumeric characters, hyphens (-) and underscores (_)."); assert_eq!(message, "Index must have a valid uid; Index uid can be of type integer or string only composed of alphanumeric characters, hyphens (-) and underscores (_).");
} }
// Test that it's possible to add identifier if it's not already set on index creation // Test that it's possible to add primary_key if it's not already set on index creation
#[test] #[test]
fn create_index_and_add_indentifier_after() { fn create_index_and_add_indentifier_after() {
let mut server = common::Server::with_uid("movies"); let mut server = common::Server::with_uid("movies");
// 1 - Create the index with no identifier // 1 - Create the index with no primary_key
let body = json!({ let body = json!({
"uid": "movies", "uid": "movies",
}); });
let (response, status_code) = server.create_index(body); let (response, status_code) = server.create_index(body);
assert_eq!(status_code, 201); assert_eq!(status_code, 201);
assert_eq!(response["identifier"], json!(null)); assert_eq!(response["primaryKey"], json!(null));
// 2 - Update the index and add an identifier. // 2 - Update the index and add an primary_key.
let body = json!({ let body = json!({
"identifier": "id", "primaryKey": "id",
}); });
let (response, status_code) = server.update_index(body); let (response, status_code) = server.update_index(body);
assert_eq!(status_code, 200); assert_eq!(status_code, 200);
eprintln!("response: {:#?}", response); eprintln!("response: {:#?}", response);
assert_eq!(response["identifier"].as_str().unwrap(), "id"); assert_eq!(response["primaryKey"].as_str().unwrap(), "id");
// 3 - Get index to verify if the identifier is good // 3 - Get index to verify if the primary_key is good
let (response, status_code) = server.get_index(); let (response, status_code) = server.get_index();
assert_eq!(status_code, 200); assert_eq!(status_code, 200);
assert_eq!(response["identifier"].as_str().unwrap(), "id"); assert_eq!(response["primaryKey"].as_str().unwrap(), "id");
} }
// Test that it's impossible to change the identifier // Test that it's impossible to change the primary_key
#[test] #[test]
fn create_index_and_update_indentifier_after() { fn create_index_and_update_indentifier_after() {
let mut server = common::Server::with_uid("movies"); let mut server = common::Server::with_uid("movies");
// 1 - Create the index with no identifier // 1 - Create the index with no primary_key
let body = json!({ let body = json!({
"uid": "movies", "uid": "movies",
"identifier": "id", "primaryKey": "id",
}); });
let (response, status_code) = server.create_index(body); let (response, status_code) = server.create_index(body);
assert_eq!(status_code, 201); assert_eq!(status_code, 201);
assert_eq!(response["identifier"].as_str().unwrap(), "id"); assert_eq!(response["primaryKey"].as_str().unwrap(), "id");
// 2 - Update the index and add an identifier. // 2 - Update the index and add an primary_key.
let body = json!({ let body = json!({
"identifier": "skuid", "primaryKey": "skuid",
}); });
let (_response, status_code) = server.update_index(body); let (_response, status_code) = server.update_index(body);
assert_eq!(status_code, 400); assert_eq!(status_code, 400);
// 3 - Get index to verify if the identifier still the first one // 3 - Get index to verify if the primary_key still the first one
let (response, status_code) = server.get_index(); let (response, status_code) = server.get_index();
assert_eq!(status_code, 200); assert_eq!(status_code, 200);
assert_eq!(response["identifier"].as_str().unwrap(), "id"); assert_eq!(response["primaryKey"].as_str().unwrap(), "id");
} }
// Test that schema inference work well // Test that schema inference work well
#[test] #[test]
fn create_index_without_identifier_and_add_document() { fn create_index_without_primary_key_and_add_document() {
let mut server = common::Server::with_uid("movies"); let mut server = common::Server::with_uid("movies");
// 1 - Create the index with no identifier // 1 - Create the index with no primary_key
let body = json!({ let body = json!({
"uid": "movies", "uid": "movies",
}); });
let (response, status_code) = server.create_index(body); let (response, status_code) = server.create_index(body);
assert_eq!(status_code, 201); assert_eq!(status_code, 201);
assert_eq!(response["identifier"], json!(null)); assert_eq!(response["primaryKey"], json!(null));
// 2 - Add a document // 2 - Add a document
@ -600,27 +600,27 @@ fn create_index_without_identifier_and_add_document() {
server.add_or_update_multiple_documents(body); server.add_or_update_multiple_documents(body);
// 3 - Get index to verify if the identifier is good // 3 - Get index to verify if the primary_key is good
let (response, status_code) = server.get_index(); let (response, status_code) = server.get_index();
assert_eq!(status_code, 200); assert_eq!(status_code, 200);
assert_eq!(response["identifier"].as_str().unwrap(), "id"); assert_eq!(response["primaryKey"].as_str().unwrap(), "id");
} }
// Test search with no identifier // Test search with no primary_key
#[test] #[test]
fn create_index_without_identifier_and_search() { fn create_index_without_primary_key_and_search() {
let mut server = common::Server::with_uid("movies"); let mut server = common::Server::with_uid("movies");
// 1 - Create the index with no identifier // 1 - Create the index with no primary_key
let body = json!({ let body = json!({
"uid": "movies", "uid": "movies",
}); });
let (response, status_code) = server.create_index(body); let (response, status_code) = server.create_index(body);
assert_eq!(status_code, 201); assert_eq!(status_code, 201);
assert_eq!(response["identifier"], json!(null)); assert_eq!(response["primaryKey"], json!(null));
// 2 - Search // 2 - Search

View File

@ -644,7 +644,7 @@ fn search_with_settings_basic() {
"desc(vote_average)" "desc(vote_average)"
], ],
"distinctAttribute": null, "distinctAttribute": null,
"identifier": "id", "primaryKey": "id",
"searchableAttributes": [ "searchableAttributes": [
"title", "title",
"tagline", "tagline",
@ -751,7 +751,7 @@ fn search_with_settings_stop_words() {
"desc(vote_average)" "desc(vote_average)"
], ],
"distinctAttribute": null, "distinctAttribute": null,
"identifier": "id", "primaryKey": "id",
"searchableAttributes": [ "searchableAttributes": [
"title", "title",
"tagline", "tagline",
@ -858,7 +858,7 @@ fn search_with_settings_synonyms() {
"desc(vote_average)" "desc(vote_average)"
], ],
"distinctAttribute": null, "distinctAttribute": null,
"identifier": "id", "primaryKey": "id",
"searchableAttributes": [ "searchableAttributes": [
"title", "title",
"tagline", "tagline",
@ -970,7 +970,7 @@ fn search_with_settings_ranking_rules() {
"desc(popularity)" "desc(popularity)"
], ],
"distinctAttribute": null, "distinctAttribute": null,
"identifier": "id", "primaryKey": "id",
"searchableAttributes": [ "searchableAttributes": [
"title", "title",
"tagline", "tagline",
@ -1077,7 +1077,7 @@ fn search_with_settings_searchable_attributes() {
"desc(vote_average)" "desc(vote_average)"
], ],
"distinctAttribute": null, "distinctAttribute": null,
"identifier": "id", "primaryKey": "id",
"searchableAttributes": [ "searchableAttributes": [
"tagline", "tagline",
"overview", "overview",
@ -1183,7 +1183,7 @@ fn search_with_settings_displayed_attributes() {
"desc(vote_average)" "desc(vote_average)"
], ],
"distinctAttribute": null, "distinctAttribute": null,
"identifier": "id", "primaryKey": "id",
"searchableAttributes": [ "searchableAttributes": [
"title", "title",
"tagline", "tagline",
@ -1254,7 +1254,7 @@ fn search_with_settings_searchable_attributes_2() {
"desc(vote_average)" "desc(vote_average)"
], ],
"distinctAttribute": null, "distinctAttribute": null,
"identifier": "id", "primaryKey": "id",
"searchableAttributes": [ "searchableAttributes": [
"tagline", "tagline",
"overview", "overview",

View File

@ -291,7 +291,7 @@ fn test_default_settings_2() {
let mut server = common::Server::with_uid("movies"); let mut server = common::Server::with_uid("movies");
let body = json!({ let body = json!({
"uid": "movies", "uid": "movies",
"identifier": "id", "primaryKey": "id",
}); });
server.create_index(body); server.create_index(body);

View File

@ -8,7 +8,7 @@ fn index_new_fields_default() {
let mut server = common::Server::with_uid("movies"); let mut server = common::Server::with_uid("movies");
let body = json!({ let body = json!({
"uid": "movies", "uid": "movies",
"identifier": "id", "primaryKey": "id",
}); });
server.create_index(body); server.create_index(body);
@ -60,7 +60,7 @@ fn index_new_fields_true() {
let mut server = common::Server::with_uid("movies"); let mut server = common::Server::with_uid("movies");
let body = json!({ let body = json!({
"uid": "movies", "uid": "movies",
"identifier": "id", "primaryKey": "id",
}); });
server.create_index(body); server.create_index(body);
@ -116,7 +116,7 @@ fn index_new_fields_false() {
let mut server = common::Server::with_uid("movies"); let mut server = common::Server::with_uid("movies");
let body = json!({ let body = json!({
"uid": "movies", "uid": "movies",
"identifier": "id", "primaryKey": "id",
}); });
server.create_index(body); server.create_index(body);
@ -169,7 +169,7 @@ fn index_new_fields_true_then_false() {
let mut server = common::Server::with_uid("movies"); let mut server = common::Server::with_uid("movies");
let body = json!({ let body = json!({
"uid": "movies", "uid": "movies",
"identifier": "id", "primaryKey": "id",
}); });
server.create_index(body); server.create_index(body);
@ -228,7 +228,7 @@ fn index_new_fields_false_then_true() {
let mut server = common::Server::with_uid("movies"); let mut server = common::Server::with_uid("movies");
let body = json!({ let body = json!({
"uid": "movies", "uid": "movies",
"identifier": "id", "primaryKey": "id",
}); });
server.create_index(body); server.create_index(body);

View File

@ -111,7 +111,7 @@ fn send_undefined_rule() {
let mut server = common::Server::with_uid("movies"); let mut server = common::Server::with_uid("movies");
let body = json!({ let body = json!({
"uid": "movies", "uid": "movies",
"identifier": "id", "primaryKey": "id",
}); });
server.create_index(body); server.create_index(body);
@ -128,7 +128,7 @@ fn send_malformed_custom_rule() {
let mut server = common::Server::with_uid("movies"); let mut server = common::Server::with_uid("movies");
let body = json!({ let body = json!({
"uid": "movies", "uid": "movies",
"identifier": "id", "primaryKey": "id",
}); });
server.create_index(body); server.create_index(body);

View File

@ -8,7 +8,7 @@ fn update_stop_words() {
let mut server = common::Server::with_uid("movies"); let mut server = common::Server::with_uid("movies");
let body = json!({ let body = json!({
"uid": "movies", "uid": "movies",
"identifier": "id", "primaryKey": "id",
}); });
server.create_index(body); server.create_index(body);

View File

@ -6,7 +6,7 @@ pub type SResult<T> = Result<T, Error>;
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
FieldNameNotFound(String), FieldNameNotFound(String),
IdentifierAlreadyPresent, PrimaryKeyAlreadyPresent,
MaxFieldsLimitExceeded, MaxFieldsLimitExceeded,
} }
@ -15,7 +15,7 @@ impl fmt::Display for Error {
use self::Error::*; use self::Error::*;
match self { match self {
FieldNameNotFound(field) => write!(f, "The field {:?} doesn't exist", field), FieldNameNotFound(field) => write!(f, "The field {:?} doesn't exist", field),
IdentifierAlreadyPresent => write!(f, "The schema already have an identifier. It's impossible to update it"), PrimaryKeyAlreadyPresent => write!(f, "The schema already have an primary key. It's impossible to update it"),
MaxFieldsLimitExceeded => write!(f, "The maximum of possible reattributed field id has been reached"), MaxFieldsLimitExceeded => write!(f, "The maximum of possible reattributed field id has been reached"),
} }
} }

View File

@ -6,7 +6,7 @@ use std::collections::{HashMap, HashSet};
pub struct Schema { pub struct Schema {
fields_map: FieldsMap, fields_map: FieldsMap,
identifier: Option<FieldId>, primary_key: Option<FieldId>,
ranked: HashSet<FieldId>, ranked: HashSet<FieldId>,
displayed: HashSet<FieldId>, displayed: HashSet<FieldId>,
@ -20,7 +20,7 @@ impl Schema {
pub fn new() -> Schema { pub fn new() -> Schema {
Schema { Schema {
fields_map: FieldsMap::default(), fields_map: FieldsMap::default(),
identifier: None, primary_key: None,
ranked: HashSet::new(), ranked: HashSet::new(),
displayed: HashSet::new(), displayed: HashSet::new(),
indexed: Vec::new(), indexed: Vec::new(),
@ -29,7 +29,7 @@ impl Schema {
} }
} }
pub fn with_identifier(name: &str) -> Schema { pub fn with_primary_key(name: &str) -> Schema {
let mut fields_map = FieldsMap::default(); let mut fields_map = FieldsMap::default();
let field_id = fields_map.insert(name).unwrap(); let field_id = fields_map.insert(name).unwrap();
@ -43,7 +43,7 @@ impl Schema {
Schema { Schema {
fields_map, fields_map,
identifier: Some(field_id), primary_key: Some(field_id),
ranked: HashSet::new(), ranked: HashSet::new(),
displayed, displayed,
indexed, indexed,
@ -52,17 +52,17 @@ impl Schema {
} }
} }
pub fn identifier(&self) -> Option<&str> { pub fn primary_key(&self) -> Option<&str> {
self.identifier.map(|id| self.fields_map.name(id).unwrap()) self.primary_key.map(|id| self.fields_map.name(id).unwrap())
} }
pub fn set_identifier(&mut self, name: &str) -> SResult<FieldId> { pub fn set_primary_key(&mut self, name: &str) -> SResult<FieldId> {
if self.identifier.is_some() { if self.primary_key.is_some() {
return Err(Error::IdentifierAlreadyPresent) return Err(Error::PrimaryKeyAlreadyPresent)
} }
let id = self.insert(name)?; let id = self.insert(name)?;
self.identifier = Some(id); self.primary_key = Some(id);
self.set_indexed(name)?; self.set_indexed(name)?;
self.set_displayed(name)?; self.set_displayed(name)?;