@@ -661,6 +661,96 @@ impl Index {
661
661
self . add_or_replace ( documents, primary_key) . await
662
662
}
663
663
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
+
664
754
/// Add a list of documents and update them if they already.
665
755
///
666
756
/// 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 {
1861
1951
assert_eq ! ( res. offset, 2 ) ;
1862
1952
}
1863
1953
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
+
1864
2008
#[ meilisearch_test]
1865
2009
async fn test_get_one_task ( client : Client , index : Index ) -> Result < ( ) , Error > {
1866
2010
let task = index
0 commit comments