Skip to content

Commit 91d0d65

Browse files
authored
Implicit index creation (#211)
1 parent 75cd43a commit 91d0d65

File tree

8 files changed

+372
-159
lines changed

8 files changed

+372
-159
lines changed

.code-samples.meilisearch.yaml

Lines changed: 88 additions & 94 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,10 @@ NB: you can also download MeiliSearch from **Homebrew** or **APT**.
8585

8686
## 🚀 Getting Started
8787

88+
#### Add Documents <!-- omit in TOC -->
89+
8890
```rust
89-
use meilisearch_sdk::{document::*, client::*, search::*};
91+
use meilisearch_sdk::{document::*, client::*};
9092
use serde::{Serialize, Deserialize};
9193
use futures::executor::block_on;
9294

@@ -110,10 +112,10 @@ fn main() { block_on(async move {
110112
// Create a client (without sending any request so that can't fail)
111113
let client = Client::new("http://localhost:7700", "masterKey");
112114

113-
// Get the index called "movies"
114-
let movies = client.get_or_create("movies").await.unwrap();
115+
// An index is where the documents are stored.
116+
let movies = client.index("movies");
115117

116-
// Add some movies in the index
118+
// Add some movies in the index. If the index 'movies' does not exist, MeiliSearch creates it when you first add the documents.
117119
movies.add_documents(&[
118120
Movie{id: 1, title: String::from("Carol"), genres: vec!["Romance".to_string(), "Drama".to_string()]},
119121
Movie{id: 2, title: String::from("Wonder Woman"), genres: vec!["Action".to_string(), "Adventure".to_string()]},
@@ -122,19 +124,64 @@ fn main() { block_on(async move {
122124
Movie{id: 5, title: String::from("Moana"), genres: vec!["Fantasy".to_string(), "Action".to_string()]},
123125
Movie{id: 6, title: String::from("Philadelphia"), genres: vec!["Drama".to_string()]},
124126
], Some("id")).await.unwrap();
125-
126-
// Query movies (note that there is a typo)
127-
println!("{:?}", movies.search().with_query("carol").execute::<Movie>().await.unwrap().hits);
128127
})}
129128
```
130129

131-
Output:
130+
#### Basic Search <!-- omit in TOC -->
132131

132+
```rust
133+
// MeiliSearch is typo-tolerant:
134+
println!("{:?}", client.index("movies").search().with_query("caorl").execute::<Movie>().await.unwrap().hits);
135+
```
136+
137+
Output:
133138
```
134139
[Movie{id: 1, title: String::from("Carol"), genres: vec!["Romance", "Drama"]}]
135140
```
136141

137-
##### Custom Search With Filters <!-- omit in TOC -->
142+
Json output:
143+
```json
144+
{
145+
"hits": [{
146+
"id": 1,
147+
"title": "Carol",
148+
"genres": ["Romance", "Drama"]
149+
}],
150+
"offset": 0,
151+
"limit": 10,
152+
"processingTimeMs": 1,
153+
"query": "caorl"
154+
}
155+
```
156+
157+
#### Custom Search <!-- omit in toc -->
158+
159+
```rust
160+
println!("{:?}", client.index("movies").search().with_query("phil").with_attributes_to_highlight(Selectors::Some(&["*"])).execute::<Movie>().await.unwrap().hits);
161+
```
162+
163+
Json output:
164+
```json
165+
{
166+
"hits": [
167+
{
168+
"id": 6,
169+
"title": "Philadelphia",
170+
"_formatted": {
171+
"id": 6,
172+
"title": "<em>Phil</em>adelphia",
173+
"genre": ["Drama"]
174+
}
175+
}
176+
],
177+
"offset": 0,
178+
"limit": 20,
179+
"processingTimeMs": 0,
180+
"query": "phil"
181+
}
182+
```
183+
184+
#### Custom Search With Filters <!-- omit in TOC -->
138185

139186
If you want to enable filtering, you must add your attributes to the `filterableAttributes`
140187
index setting.
@@ -144,7 +191,7 @@ let filterable_attributes = [
144191
"id",
145192
"genres"
146193
];
147-
movies.set_filterable_attributes(&filterable_attributes).await.unwrap();
194+
client.index("movies").set_filterable_attributes(&filterable_attributes).await.unwrap();
148195
```
149196

150197
You only need to perform this operation once.
@@ -157,10 +204,11 @@ status](https://docs.meilisearch.com/reference/api/updates.html#get-an-update-st
157204
Then, you can perform the search:
158205

159206
```rust
160-
println!("{:?}", movies.search().with_query("wonder").with_filter("id > 1 AND genres = Action")
207+
println!("{:?}", client.index("movies").search().with_query("wonder").with_filter("id > 1 AND genres = Action")
161208
.execute::<Movie>().await.unwrap().hits);
162209
```
163210

211+
Json output:
164212
```json
165213
{
166214
"hits": [

examples/web_app/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ impl Component for Model {
4949
Self {
5050
link: Rc::new(link),
5151

52-
// The assume_index method avoids checking the existence of the index.
52+
// The index method avoids checking the existence of the index.
5353
// It won't make any HTTP request so the function is not async so it's easier to use.
5454
// Use only if you are sure that the index exists.
55-
index: Rc::new(CLIENT.assume_index("crates")),
55+
index: Rc::new(CLIENT.index("crates")),
5656
results: Vec::new(),
5757
processing_time_ms: 0,
5858

src/client.rs

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl Client {
8181
Ok(json_indexes)
8282
}
8383

84-
/// Get an [index](../indexes/struct.Index.html).
84+
/// Get an [index](../indexes/struct.Index.html), this index should already exist.
8585
///
8686
/// # Example
8787
///
@@ -104,7 +104,7 @@ impl Client {
104104
}
105105
}
106106

107-
/// Get a raw JSON [index](../indexes/struct.Index.html).
107+
/// Get a raw JSON [index](../indexes/struct.Index.html), this index should already exist.
108108
///
109109
/// # Example
110110
///
@@ -120,17 +120,13 @@ impl Client {
120120
/// let movies = client.get_raw_index("movies").await.unwrap();
121121
/// # });
122122
/// ```
123+
/// If you use it directly from an index, you can use the method [fetch_info](#method.fetch_info), which is the equivalent method from an index.
123124
pub async fn get_raw_index(&self, uid: impl AsRef<str>) -> Result<JsonIndex, Error> {
124-
Ok(request::<(), JsonIndex>(
125-
&format!("{}/indexes/{}", self.host, uid.as_ref()),
126-
&self.api_key,
127-
Method::Get,
128-
200,
129-
).await?)
125+
Index::fetch_info(&self.index(uid.as_ref())).await
130126
}
131127

132-
/// Assume that an [index](../indexes/struct.Index.html) exist and create a corresponding object without any check.
133-
pub fn assume_index(&self, uid: impl Into<String>) -> Index {
128+
/// Create a corresponding object of an [index](../indexes/struct.Index.html) without any check or doing an HTTP call.
129+
pub fn index(&self, uid: impl Into<String>) -> Index {
134130
Index {
135131
uid: Rc::new(uid.into()),
136132
host: Rc::clone(&self.host),
@@ -383,7 +379,18 @@ mod tests {
383379
#[async_test]
384380
async fn test_get_keys() {
385381
let client = Client::new("http://localhost:7700", "masterKey");
386-
client.get_keys().await.unwrap();
382+
let keys = client.get_keys().await.unwrap();
383+
assert!(keys.private.is_some());
384+
assert!(keys.public.is_some());
385+
}
386+
387+
#[async_test]
388+
async fn test_get_index() {
389+
let client = Client::new("http://localhost:7700", "masterKey");
390+
let index_name = "get_index";
391+
client.create_index(index_name, None).await.unwrap();
392+
let index = client.get_index(index_name).await.unwrap();
393+
assert_eq!(index.uid.to_string(), index_name);
387394
}
388395

389396
#[async_test]
@@ -431,4 +438,33 @@ mod tests {
431438
let deleted = client.delete_index_if_exists("bad").await.unwrap();
432439
assert_eq!(deleted, false);
433440
}
441+
442+
#[async_test]
443+
async fn test_fetch_info() {
444+
let client = Client::new("http://localhost:7700", "masterKey");
445+
let index_name = "fetch_info";
446+
client.create_index(index_name, None).await.unwrap();
447+
let index = client.index(index_name).fetch_info().await;
448+
assert!(index.is_ok());
449+
}
450+
451+
#[async_test]
452+
async fn test_get_primary_key_is_none() {
453+
let client = Client::new("http://localhost:7700", "masterKey");
454+
let index_name = "get_primary_key_is_none";
455+
client.create_index(index_name, None).await.unwrap();
456+
let primary_key = client.index(index_name).get_primary_key().await;
457+
assert!(primary_key.is_ok());
458+
assert!(primary_key.unwrap().is_none());
459+
}
460+
461+
#[async_test]
462+
async fn test_get_primary_key() {
463+
let client = Client::new("http://localhost:7700", "masterKey");
464+
let index_name = "get_primary_key";
465+
client.create_index(index_name, Some("primary_key")).await.unwrap();
466+
let primary_key = client.index(index_name).get_primary_key().await;
467+
assert!(primary_key.is_ok());
468+
assert_eq!(primary_key.unwrap().unwrap(), "primary_key");
469+
}
434470
}

0 commit comments

Comments
 (0)