Skip to content

Commit 2f4c5e6

Browse files
committed
Added and udpdated document ndjson
Signed-off-by: carlosb1 <[email protected]>
1 parent 8b3685a commit 2f4c5e6

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed

src/indexes.rs

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,96 @@ impl Index {
661661
self.add_or_replace(documents, primary_key).await
662662
}
663663

664+
/// Add a raw ndjson payload and update them if they already.
665+
///
666+
/// It configures the correct content type for ndjson data.
667+
///
668+
/// If you send an already existing document (same id) the old document will be only partially updated according to the fields of the new document.
669+
/// Thus, any fields not present in the new document are kept and remained unchanged.
670+
///
671+
/// To completely overwrite a document, check out the [`Index::add_documents_ndjson`] documents method.
672+
///
673+
/// # Example
674+
///
675+
/// ```
676+
/// # use serde::{Serialize, Deserialize};
677+
/// # use meilisearch_sdk::{client::*, indexes::*};
678+
/// # use std::thread::sleep;
679+
/// # use std::time::Duration;
680+
/// #
681+
/// # let MEILISEARCH_URL = option_env!("MEILISEARCH_URL").unwrap_or("http://localhost:7700");
682+
/// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey");
683+
/// # futures::executor::block_on(async move {
684+
/// # let client = Client::new(MEILISEARCH_URL, Some(MEILISEARCH_API_KEY));
685+
/// let movie_index = client.index("update_documents_ndjson");
686+
///
687+
/// let task = movie_index.update_documents_ndjson(
688+
/// r#"{ "id": 1, "body": "doggo" }
689+
/// { "id": 2, "body": "catto" }"#.as_bytes(),
690+
/// Some("id"),
691+
/// ).await.unwrap();
692+
/// // Meilisearch may take some time to execute the request so we are going to wait till it's completed
693+
/// client.wait_for_task(task, None, None).await.unwrap();
694+
///
695+
/// let movies = movie_index.get_documents::<serde_json::Value>().await.unwrap();
696+
/// assert!(movies.results.len() == 2);
697+
/// # movie_index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap();
698+
/// # });
699+
/// ```
700+
pub async fn update_documents_ndjson<T: futures_io::AsyncRead + Send + Sync + 'static>(
701+
&self,
702+
payload: T,
703+
primary_key: Option<&str>,
704+
) -> Result<TaskInfo, Error> {
705+
self.add_or_update_unchecked_payload(payload, "application/x-ndjson", primary_key)
706+
.await
707+
}
708+
709+
/// Add a raw ndjson payload to meilisearch.
710+
///
711+
/// It configures the correct content type for ndjson data.
712+
///
713+
/// If you send an already existing document (same id) the **whole existing document** will be overwritten by the new document.
714+
/// Fields previously in the document not present in the new document are removed.
715+
///
716+
/// For a partial update of the document see [`Index::update_documents_ndjson`].
717+
///
718+
/// # Example
719+
///
720+
/// ```
721+
/// # use serde::{Serialize, Deserialize};
722+
/// # use meilisearch_sdk::{client::*, indexes::*};
723+
/// # use std::thread::sleep;
724+
/// # use std::time::Duration;
725+
/// #
726+
/// # let MEILISEARCH_URL = option_env!("MEILISEARCH_URL").unwrap_or("http://localhost:7700");
727+
/// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey");
728+
/// # futures::executor::block_on(async move {
729+
/// # let client = Client::new(MEILISEARCH_URL, Some(MEILISEARCH_API_KEY));
730+
/// let movie_index = client.index("add_documents_ndjson");
731+
///
732+
/// let task = movie_index.add_documents_ndjson(
733+
/// r#"{ "id": 1, "body": "doggo" }
734+
/// { "id": 2, "body": "catto" }"#.as_bytes(),
735+
/// Some("id"),
736+
/// ).await.unwrap();
737+
/// // Meilisearch may take some time to execute the request so we are going to wait till it's completed
738+
/// client.wait_for_task(task, None, None).await.unwrap();
739+
///
740+
/// let movies = movie_index.get_documents::<serde_json::Value>().await.unwrap();
741+
/// assert!(movies.results.len() == 2);
742+
/// # movie_index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap();
743+
/// # });
744+
/// ```
745+
pub async fn add_documents_ndjson<T: futures_io::AsyncRead + Send + Sync + 'static>(
746+
&self,
747+
payload: T,
748+
primary_key: Option<&str>,
749+
) -> Result<TaskInfo, Error> {
750+
self.add_or_replace_unchecked_payload(payload, "application/x-ndjson", primary_key)
751+
.await
752+
}
753+
664754
/// Add a list of documents and update them if they already.
665755
///
666756
/// If you send an already existing document (same id) the old document will be only partially updated according to the fields of the new document.
@@ -1861,6 +1951,60 @@ mod tests {
18611951
assert_eq!(res.offset, 2);
18621952
}
18631953

1954+
#[meilisearch_test]
1955+
async fn test_add_documents_ndjson(client: Client, index: Index) -> Result<(), Error> {
1956+
let ndjson = r#"{ "id": 1, "body": "doggo" }{ "id": 2, "body": "catto" }"#.as_bytes();
1957+
1958+
let task = index
1959+
.add_documents_ndjson(ndjson, Some("id"))
1960+
.await?
1961+
.wait_for_completion(&client, None, None)
1962+
.await?;
1963+
1964+
let status = index.get_task(task).await?;
1965+
// Meilisearch may take some time to execute the request so we are going to wait till it's completed
1966+
let elements = index.get_documents::<serde_json::Value>().await.unwrap();
1967+
assert!(matches!(status, Task::Succeeded { .. }));
1968+
assert!(elements.results.len() == 2);
1969+
1970+
Ok(())
1971+
}
1972+
1973+
#[meilisearch_test]
1974+
async fn test_update_documents_ndjson(client: Client, index: Index) -> Result<(), Error> {
1975+
let old_ndjson = r#"{ "id": 1, "body": "doggo" }{ "id": 2, "body": "catto" }"#.as_bytes();
1976+
let updated_ndjson =
1977+
r#"{ "id": 1, "second_body": "second_doggo" }{ "id": 2, "second_body": "second_catto" }"#.as_bytes();
1978+
// Add first njdson document
1979+
let task = index
1980+
.add_documents_ndjson(old_ndjson, Some("id"))
1981+
.await?
1982+
.wait_for_completion(&client, None, None)
1983+
.await?;
1984+
let _ = index.get_task(task).await?;
1985+
1986+
let task = index
1987+
.update_documents_ndjson(updated_ndjson, Some("id"))
1988+
.await?
1989+
.wait_for_completion(&client, None, None)
1990+
.await?;
1991+
1992+
let status = index.get_task(task).await?;
1993+
let elements = index.get_documents::<serde_json::Value>().await.unwrap();
1994+
1995+
assert!(matches!(status, Task::Succeeded { .. }));
1996+
assert!(elements.results.len() == 2);
1997+
1998+
let expected_result = vec![
1999+
json!( {"body": "doggo", "id": 1, "second_body": "second_doggo"}),
2000+
json!( {"body": "catto", "id": 2, "second_body": "second_catto"}),
2001+
];
2002+
2003+
assert_eq!(elements.results, expected_result);
2004+
2005+
Ok(())
2006+
}
2007+
18642008
#[meilisearch_test]
18652009
async fn test_get_one_task(client: Client, index: Index) -> Result<(), Error> {
18662010
let task = index

0 commit comments

Comments
 (0)