Skip to content

Commit 1efe89a

Browse files
authored
README: documentation for the derive (#61)
1 parent f89cdc7 commit 1efe89a

File tree

2 files changed

+148
-1
lines changed

2 files changed

+148
-1
lines changed

README.md

Lines changed: 143 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,149 @@
55

66
Community-maintained Rust client library for Typesense | Work In Progress & Help Wanted!
77

8-
### Development
8+
## Collection schema derive
9+
10+
Apply `#[derive(Typesense)]` to any struct you want to index in Typesense. The macro generates:
11+
12+
- a `collection_schema()` definition based on your struct fields and attributes.
13+
- a `{struct_name}Partial` struct for partial updates of Typesense documents.
14+
15+
### Quick example
16+
17+
```rust
18+
#[derive(Typesense, Serialize, Deserialize)]
19+
#[typesense(
20+
collection_name = "mega_products",
21+
default_sorting_field = "price",
22+
symbols_to_index = ["+", "-"]
23+
)]
24+
struct MegaProduct {
25+
id: String,
26+
27+
#[typesense(infix, stem)]
28+
title: String,
29+
30+
#[typesense(facet)]
31+
brand: String,
32+
33+
#[typesense(sort)]
34+
price: f32,
35+
36+
#[typesense(rename = "product_name", sort = true)]
37+
#[serde(rename = "product_name")]
38+
official_name: String,
39+
}
40+
41+
// update a Typesense document using the generated partial struct
42+
let update_payload = MegaProductPartial {
43+
price: Some(25.99),
44+
..Default::default()
45+
};
46+
47+
let result = client
48+
.collection::<MegaProduct>()
49+
.document("product-1")
50+
.update(&update_payload, None)
51+
.await;
52+
```
53+
54+
### Supported collection parameters
55+
56+
| Key | Type | Description / Notes |
57+
| ----------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
58+
| `collection_name` | string | Defaults to the struct name in lowercase |
59+
| `default_sorting_field` | string | Must match the field name after `rename` if used |
60+
| `enable_nested_fields` | bool | Enables Typesense nested field support |
61+
| `token_separators` | list of strings | List of symbols or special characters to be used for splitting the text into individual words in addition to space and new-line characters. |
62+
| `symbols_to_index` | list of strings | List of symbols or special characters to be indexed. |
63+
64+
### Supported field parameter
65+
66+
| Attribute | Type | Description / Notes |
67+
| ------------- | ------- | --------------------------------------------------------------------------------------------------------------------- |
68+
| `facet` | bool | Enable faceting for the field |
69+
| `sort` | bool | Marks the field as sortable |
70+
| `index` | bool | Whether to index the field in memmory |
71+
| `store` | bool | Whether to store the field on disk |
72+
| `infix` | bool | Enables infix search |
73+
| `stem` | bool | Values are stemmed before indexing in-memory. |
74+
| `range_index` | bool | Enables an index optimized for range filtering on numerical fields |
75+
| `optional` | bool | Fields with type `Option<T>` are optional in the generated Typesense schema. Setting this attribute will override it. |
76+
| `num_dim` | integer | Set this to a non-zero value to treat a field of type `float[]` as a vector field. |
77+
| `locale` | string | Locale for text processing |
78+
| `vec_dist` | string | Distance metric to be used for vector search |
79+
| `type` | string | Override the field type in Typesense |
80+
| `rename` | string | Rename the field in the Typesense schema |
81+
| `flatten` | -- | Generate Typesense field schemas for a nested struct |
82+
| `skip` | -- | Skips this field in the Typesense schema |
83+
84+
All boolean attributes can be either set to `true` using shorthand flags or explicitly set a value `=true/false`. Example:
85+
86+
```rust
87+
#[typesense(facet)]
88+
brand: String,
89+
90+
#[typesense(facet = false)]
91+
weight: f32,
92+
```
93+
94+
#### Indexing nested objects
95+
96+
When you have fields that are also structs, you need to mark all structs with `#[derive(Typesense)]`. The generated Typesense schema for those fields will have type of `object` (or `object[]` if the field is a vector).
97+
98+
Applying `#[typesense(flatten)]` on a field will expand the nested field schemas into the parent.
99+
100+
```rust
101+
#[typesense(flatten)]
102+
supplier: SupplierInfo,
103+
```
104+
105+
If the field has a rename:
106+
107+
```rust
108+
#[typesense(flatten, rename = "logistics_data")]
109+
logistics: Logistics,
110+
```
111+
112+
flattened fields become `logistics_data.field_name`.
113+
114+
`#[typesense(flatten, skip)]` produces only the flattened fields and omits the parent object field.
115+
116+
#### Nested objects example:
117+
118+
```rust
119+
#[derive(Typesense, Serialize, Deserialize)]
120+
struct ProductDetails {
121+
#[typesense(facet)]
122+
part_number: String,
123+
#[typesense(skip)]
124+
description: String,
125+
}
126+
127+
#[derive(Typesense, Serialize, Deserialize)]
128+
#[typesense(
129+
collection_name = "mega_products",
130+
)]
131+
struct MegaProduct {
132+
#[typesense(flatten)]
133+
details: ProductDetails,
134+
}
135+
```
136+
137+
Will generate this schema:
138+
139+
```jsonc
140+
{
141+
"name": "mega_products"
142+
"fields": [
143+
{"name": "details", "type": "object"}, // <-- `#[typesense(flatten, skip)]` will omit this field
144+
{"name": "details.part_number", "type": "string", "facet": true}
145+
// `description` is skipped
146+
],
147+
}
148+
```
149+
150+
## Development
9151

10152
When updating or adding new parameters and endpoints, make changes directly in the [Typesense API spec repository](https://github.com/typesense/typesense-api-spec).
11153

typesense/tests/derive/collection.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ struct KitchenSinkProduct {
107107

108108
hash_map_vec: Vec<HashMap<String, i32>>,
109109
btree_map_vec: Vec<BTreeMap<String, i32>>,
110+
// optional = false should override the Option<T> type
111+
#[typesense(optional = false)]
112+
optional_field: Option<i32>,
110113
}
111114

112115
#[test]
@@ -132,6 +135,8 @@ fn derived_document_handles_all_attributes() {
132135

133136
{ "name": "hash_map_vec", "type": "object[]" },
134137
{ "name": "btree_map_vec", "type": "object[]" },
138+
139+
{ "name": "optional_field", "type": "int32", "optional": false },
135140
],
136141
"default_sorting_field": "renamed_price",
137142
"token_separators": ["-", "/"],

0 commit comments

Comments
 (0)