typesense / typesense-rust

Rust client for Typesense | Work In Progress & Help Wanted
Apache License 2.0
32 stars 12 forks source link

Collections API #7

Closed morenol closed 3 years ago

morenol commented 3 years ago

Description

We need the Collections API, here is my proposal for this. Add your comments in this issue to talk about the design of the Collections API

Specification

I think that we can implement a macro for this.

Example

#[derive(Debug, Serialize, Deserialize, TypesenseCollection)]
#[typesense_collection(default_sorting_key=num_of_employees)]
pub struct Company {
    company_name: String,
    num_employees: usize,
   #[typesense_collection(facet)]
    country: Country
}

#[derive(Debug, Serialize, Deserialize)]
enum Country {
...

That macro should implement the schema needed to create a Collection.

Specifically, a trait like this one:

pub impl Collection : Serialize {
    fn schema(&self) -> CollectionSchema;
}

Where CollectionSchema should be compatible with the things that typesense expects, i.e:

#[derive(Debug, Serialize, Deserialize)]
pub struct CollectionSchema{
    name: String,
    fields: Vec<Field>,
    default_sorting_field: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct Field {
    name: String,
    #[serde(rename = "type")]
    typesense_type: TypesenseType,
    optional: Option<bool>,
    facet: Option<bool>,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum TypesenseType {
    String,
    Int32,
    ...
}

Client Interface

Features needed:

I am still not sure how should be the interface of the library client to create, delete, retrieve or list the collections.

In the other libraries, they do something like:

client.collections.create(schema)
client.collections['companies'].delete()
client.collections['companies'].retrieve()
client.collections.retrieve()

Maybe something like this:

impl Client<T: Transport> {
     pub fn collection<C: Collection>>(&self) -> CollectionClient<T, C>;
}

Where the CollectionClient struct has retrieve, delete and create implementations.

morenol commented 3 years ago

What do you think about this? @emmanuelantony2000

Maybe I can start with the typsense-derive crate, and then we can think in how we can integrate that with the client.

DanSnow commented 3 years ago

I think the collection API should be something like fn collection<T: Collection>(&self) -> CollectionClient<T>, or the API will be hard to use in my opinion.

emmanuelantony2000 commented 3 years ago

What do you think about this? @emmanuelantony2000

Maybe I can start with the typsense-derive crate, and then we can think in how we can integrate that with the client.

That sounds good!

In the other libraries, they do something like:

client.collections.create(schema)
client.collections['companies'].delete()
client.collections['companies'].retrieve()
client.collections.retrieve()

It might be possible in Rust, using Index and/or IndexMut traits.

DanSnow commented 3 years ago

In the other libraries, they do something like:

client.collections.create(schema)
client.collections['companies'].delete()
client.collections['companies'].retrieve()
client.collections.retrieve()

It might be possible in Rust with Index or IndexMut traits. However, because this will force users to provide collection name and type separately, e.g. client.collection["companies"].retrieve::<Company>(). We will lose some power of static checking. With the collection, we can force users to tie collection name and their type together to prevent a user from using an unrelated type with a collection.