Skip to content

Commit a4d4a9e

Browse files
committed
Implement broken test
1 parent 57edc89 commit a4d4a9e

File tree

2 files changed

+58
-56
lines changed

2 files changed

+58
-56
lines changed

src/request.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ pub trait HttpClient: Clone + Send + Sync {
8181
{
8282
use futures::io::Cursor;
8383

84+
println!("Body: {}", serde_json::to_string(&method.body()).unwrap());
85+
8486
self.stream_request(
8587
url,
8688
method.map_body(|body| Cursor::new(to_vec(&body).unwrap())),

src/search.rs

Lines changed: 56 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,11 @@ impl<'a, Http: HttpClient> SearchQuery<'a, Http> {
652652
}
653653

654654
/// Use a custom vector to perform a search query
655+
///
656+
/// `vector` is mandatory when performing searches with `userProvided` embedders.
657+
/// You may also use `vector` to override an embedder’s automatic vector generation.
658+
///
659+
/// `vector` dimensions must match the dimensions of the embedder.
655660
pub fn with_vector<'b>(&'b mut self, vector: &'a [f32]) -> &'b mut SearchQuery<'a, Http> {
656661
self.vector = Some(vector);
657662
self
@@ -953,12 +958,13 @@ mod tests {
953958
#[derive(Debug, Serialize, Deserialize, PartialEq)]
954959
struct Vectors(HashMap<String, Vector>);
955960

956-
impl From<&[f32; 1]> for Vectors {
957-
fn from(value: &[f32; 1]) -> Self {
961+
impl<T: Into<Vec<f32>>> From<T> for Vectors {
962+
fn from(value: T) -> Self {
963+
let vec: Vec<f32> = value.into();
958964
Vectors(HashMap::from([(
959965
S("default"),
960966
Vector {
961-
embeddings: SingleOrMultipleVectors::Multiple(Vec::from([value.to_vec()])),
967+
embeddings: SingleOrMultipleVectors::Multiple(Vec::from([vec])),
962968
regenerate: false,
963969
},
964970
)]))
@@ -974,18 +980,25 @@ mod tests {
974980
}
975981
}
976982

983+
fn vectorize(is_harry_potter: bool, id: usize) -> Vec<f32> {
984+
let mut vector: Vec<f32> = vec![0.; 11];
985+
vector[0] = if is_harry_potter { 1. } else { 0. };
986+
vector[id + 1] = 1.;
987+
vector
988+
}
989+
977990
async fn setup_test_index(client: &Client, index: &Index) -> Result<(), Error> {
978991
let t0 = index.add_documents(&[
979-
Document { id: 0, kind: "text".into(), number: 0, value: S("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."), nested: Nested { child: S("first") }, _vectors: Some(Vectors::from(&[1000.0]))},
980-
Document { id: 1, kind: "text".into(), number: 10, value: S("dolor sit amet, consectetur adipiscing elit"), nested: Nested { child: S("second") }, _vectors: Some(Vectors::from(&[2000.0])) },
981-
Document { id: 2, kind: "title".into(), number: 20, value: S("The Social Network"), nested: Nested { child: S("third") }, _vectors: Some(Vectors::from(&[3000.0])) },
982-
Document { id: 3, kind: "title".into(), number: 30, value: S("Harry Potter and the Sorcerer's Stone"), nested: Nested { child: S("fourth") }, _vectors: Some(Vectors::from(&[4000.0])) },
983-
Document { id: 4, kind: "title".into(), number: 40, value: S("Harry Potter and the Chamber of Secrets"), nested: Nested { child: S("fift") }, _vectors: Some(Vectors::from(&[5000.0])) },
984-
Document { id: 5, kind: "title".into(), number: 50, value: S("Harry Potter and the Prisoner of Azkaban"), nested: Nested { child: S("sixth") }, _vectors: Some(Vectors::from(&[6000.0])) },
985-
Document { id: 6, kind: "title".into(), number: 60, value: S("Harry Potter and the Goblet of Fire"), nested: Nested { child: S("seventh") }, _vectors: Some(Vectors::from(&[7000.0])) },
986-
Document { id: 7, kind: "title".into(), number: 70, value: S("Harry Potter and the Order of the Phoenix"), nested: Nested { child: S("eighth") }, _vectors: Some(Vectors::from(&[8000.0])) },
987-
Document { id: 8, kind: "title".into(), number: 80, value: S("Harry Potter and the Half-Blood Prince"), nested: Nested { child: S("ninth") }, _vectors: Some(Vectors::from(&[9000.0])) },
988-
Document { id: 9, kind: "title".into(), number: 90, value: S("Harry Potter and the Deathly Hallows"), nested: Nested { child: S("tenth") }, _vectors: Some(Vectors::from(&[10000.0])) },
992+
Document { id: 0, kind: "text".into(), number: 0, value: S("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."), nested: Nested { child: S("first") }, _vectors: Some(Vectors::from(vectorize(false, 0))) },
993+
Document { id: 1, kind: "text".into(), number: 10, value: S("dolor sit amet, consectetur adipiscing elit"), nested: Nested { child: S("second") }, _vectors: Some(Vectors::from(vectorize(false, 1))) },
994+
Document { id: 2, kind: "title".into(), number: 20, value: S("The Social Network"), nested: Nested { child: S("third") }, _vectors: Some(Vectors::from(vectorize(false, 2))) },
995+
Document { id: 3, kind: "title".into(), number: 30, value: S("Harry Potter and the Sorcerer's Stone"), nested: Nested { child: S("fourth") }, _vectors: Some(Vectors::from(vectorize(true, 3))) },
996+
Document { id: 4, kind: "title".into(), number: 40, value: S("Harry Potter and the Chamber of Secrets"), nested: Nested { child: S("fift") }, _vectors: Some(Vectors::from(vectorize(true, 4))) },
997+
Document { id: 5, kind: "title".into(), number: 50, value: S("Harry Potter and the Prisoner of Azkaban"), nested: Nested { child: S("sixth") }, _vectors: Some(Vectors::from(vectorize(true, 5))) },
998+
Document { id: 6, kind: "title".into(), number: 60, value: S("Harry Potter and the Goblet of Fire"), nested: Nested { child: S("seventh") }, _vectors: Some(Vectors::from(vectorize(true, 6))) },
999+
Document { id: 7, kind: "title".into(), number: 70, value: S("Harry Potter and the Order of the Phoenix"), nested: Nested { child: S("eighth") }, _vectors: Some(Vectors::from(vectorize(true, 7))) },
1000+
Document { id: 8, kind: "title".into(), number: 80, value: S("Harry Potter and the Half-Blood Prince"), nested: Nested { child: S("ninth") }, _vectors: Some(Vectors::from(vectorize(true, 8))) },
1001+
Document { id: 9, kind: "title".into(), number: 90, value: S("Harry Potter and the Deathly Hallows"), nested: Nested { child: S("tenth") }, _vectors: Some(Vectors::from(vectorize(true, 9))) },
9891002
], None).await?;
9901003
let t1 = index
9911004
.set_filterable_attributes(["kind", "value", "number"])
@@ -999,6 +1012,21 @@ mod tests {
9991012
Ok(())
10001013
}
10011014

1015+
async fn setup_hybrid_searching(client: &Client, index: &Index) -> Result<(), Error> {
1016+
use crate::settings::{Embedder, UserProvidedEmbedderSettings};
1017+
let embedder_setting =
1018+
Embedder::UserProvided(UserProvidedEmbedderSettings { dimensions: 11 });
1019+
index
1020+
.set_settings(&crate::settings::Settings {
1021+
embedders: Some(HashMap::from([("default".to_string(), embedder_setting)])),
1022+
..crate::settings::Settings::default()
1023+
})
1024+
.await?
1025+
.wait_for_completion(client, None, None)
1026+
.await?;
1027+
Ok(())
1028+
}
1029+
10021030
#[meilisearch_test]
10031031
async fn test_multi_search(client: Client, index: Index) -> Result<(), Error> {
10041032
setup_test_index(&client, &index).await?;
@@ -1594,22 +1622,6 @@ mod tests {
15941622
Ok(())
15951623
}
15961624

1597-
/// Enable vector searching and configure an userProvided embedder
1598-
async fn setup_hybrid_searching(client: &Client, index: &Index) -> Result<(), Error> {
1599-
use crate::settings::{Embedder, UserProvidedEmbedderSettings};
1600-
let embedder_setting =
1601-
Embedder::UserProvided(UserProvidedEmbedderSettings { dimensions: 1 });
1602-
index
1603-
.set_settings(&crate::settings::Settings {
1604-
embedders: Some(HashMap::from([("default".to_string(), embedder_setting)])),
1605-
..crate::settings::Settings::default()
1606-
})
1607-
.await?
1608-
.wait_for_completion(client, None, None)
1609-
.await?;
1610-
Ok(())
1611-
}
1612-
16131625
#[meilisearch_test]
16141626
async fn test_facet_search_base(client: Client, index: Index) -> Result<(), Error> {
16151627
setup_test_index(&client, &index).await?;
@@ -1684,8 +1696,8 @@ mod tests {
16841696
.execute()
16851697
.await?;
16861698
assert_eq!(results.hits.len(), 1);
1687-
let expected = Vectors::from(&[1000.0]);
1688-
assert_eq!(results.hits[0].result._vectors, Some(expected));
1699+
let expected = Some(Vectors::from(vectorize(false, 0)));
1700+
assert_eq!(results.hits[0].result._vectors, expected);
16891701

16901702
let results: SearchResults<Document> = index
16911703
.search()
@@ -1699,33 +1711,21 @@ mod tests {
16991711
}
17001712

17011713
#[meilisearch_test]
1702-
async fn test_hybrid() -> Result<(), Error> {
1703-
// this is mocked as I could not get the hybrid searching to work
1704-
// See https://github.com/meilisearch/meilisearch-rust/pull/554 for further context
1705-
let mut s = mockito::Server::new_async().await;
1706-
let mock_server_url = s.url();
1707-
let client = Client::new(mock_server_url, None::<String>)?;
1708-
let index = client.index("mocked_index");
1709-
1710-
let req = r#"{"q":"hello hybrid searching","hybrid":{"embedder":"default","semanticRatio":0.0},"vector":[1000.0]}"#.to_string();
1711-
let response = r#"{"hits":[],"offset":null,"limit":null,"estimatedTotalHits":null,"page":null,"hitsPerPage":null,"totalHits":null,"totalPages":null,"facetDistribution":null,"facetStats":null,"processingTimeMs":0,"query":"","indexUid":null}"#.to_string();
1712-
let mock_res = s
1713-
.mock("POST", "/indexes/mocked_index/search")
1714-
.with_status(200)
1715-
.match_body(mockito::Matcher::Exact(req))
1716-
.with_body(&response)
1717-
.expect(1)
1718-
.create_async()
1719-
.await;
1720-
let results: Result<SearchResults<Document>, Error> = index
1714+
async fn test_hybrid(client: Client, index: Index) -> Result<(), Error> {
1715+
setup_hybrid_searching(&client, &index).await?;
1716+
setup_test_index(&client, &index).await?;
1717+
1718+
// Search for an Harry Potter that but with lorem ipsum's id
1719+
// Will yield lorem ipsum first, them harry potter documents, then the rest
1720+
let results: SearchResults<Document> = index
17211721
.search()
1722-
.with_query("hello hybrid searching")
1723-
.with_hybrid("default", 0.0)
1724-
.with_vector(&[1000.0])
1722+
.with_hybrid("default", 1.0)
1723+
.with_vector(&vectorize(true, 0))
17251724
.execute()
1726-
.await;
1727-
mock_res.assert_async().await;
1728-
results?; // purposely not done above to have better debugging output
1725+
.await?;
1726+
let ids = results.hits.iter().map(|hit| hit.result.id).collect::<Vec<_>>();
1727+
assert_eq!(ids, vec![0, 3, 4, 5, 6, 7, 8, 9, 1, 2]);
1728+
17291729
Ok(())
17301730
}
17311731

0 commit comments

Comments
 (0)