@@ -661,6 +661,98 @@ 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
+ #[ cfg( not( target_arch = "wasm32" ) ) ]
701
+ pub async fn update_documents_ndjson < T : futures_io:: AsyncRead + Send + Sync + ' static > (
702
+ & self ,
703
+ payload : T ,
704
+ primary_key : Option < & str > ,
705
+ ) -> Result < TaskInfo , Error > {
706
+ self . add_or_update_unchecked_payload ( payload, "application/x-ndjson" , primary_key)
707
+ . await
708
+ }
709
+
710
+ /// Add a raw ndjson payload to meilisearch.
711
+ ///
712
+ /// It configures the correct content type for ndjson data.
713
+ ///
714
+ /// If you send an already existing document (same id) the **whole existing document** will be overwritten by the new document.
715
+ /// Fields previously in the document not present in the new document are removed.
716
+ ///
717
+ /// For a partial update of the document see [`Index::update_documents_ndjson`].
718
+ ///
719
+ /// # Example
720
+ ///
721
+ /// ```
722
+ /// # use serde::{Serialize, Deserialize};
723
+ /// # use meilisearch_sdk::{client::*, indexes::*};
724
+ /// # use std::thread::sleep;
725
+ /// # use std::time::Duration;
726
+ /// #
727
+ /// # let MEILISEARCH_URL = option_env!("MEILISEARCH_URL").unwrap_or("http://localhost:7700");
728
+ /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey");
729
+ /// # futures::executor::block_on(async move {
730
+ /// # let client = Client::new(MEILISEARCH_URL, Some(MEILISEARCH_API_KEY));
731
+ /// let movie_index = client.index("add_documents_ndjson");
732
+ ///
733
+ /// let task = movie_index.add_documents_ndjson(
734
+ /// r#"{ "id": 1, "body": "doggo" }
735
+ /// { "id": 2, "body": "catto" }"#.as_bytes(),
736
+ /// Some("id"),
737
+ /// ).await.unwrap();
738
+ /// // Meilisearch may take some time to execute the request so we are going to wait till it's completed
739
+ /// client.wait_for_task(task, None, None).await.unwrap();
740
+ ///
741
+ /// let movies = movie_index.get_documents::<serde_json::Value>().await.unwrap();
742
+ /// assert!(movies.results.len() == 2);
743
+ /// # movie_index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap();
744
+ /// # });
745
+ /// ```
746
+ #[ cfg( not( target_arch = "wasm32" ) ) ]
747
+ pub async fn add_documents_ndjson < T : futures_io:: AsyncRead + Send + Sync + ' static > (
748
+ & self ,
749
+ payload : T ,
750
+ primary_key : Option < & str > ,
751
+ ) -> Result < TaskInfo , Error > {
752
+ self . add_or_replace_unchecked_payload ( payload, "application/x-ndjson" , primary_key)
753
+ . await
754
+ }
755
+
664
756
/// Add a list of documents and update them if they already.
665
757
///
666
758
/// 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 +1953,60 @@ mod tests {
1861
1953
assert_eq ! ( res. offset, 2 ) ;
1862
1954
}
1863
1955
1956
+ #[ meilisearch_test]
1957
+ async fn test_add_documents_ndjson ( client : Client , index : Index ) -> Result < ( ) , Error > {
1958
+ let ndjson = r#"{ "id": 1, "body": "doggo" }{ "id": 2, "body": "catto" }"# . as_bytes ( ) ;
1959
+
1960
+ let task = index
1961
+ . add_documents_ndjson ( ndjson, Some ( "id" ) )
1962
+ . await ?
1963
+ . wait_for_completion ( & client, None , None )
1964
+ . await ?;
1965
+
1966
+ let status = index. get_task ( task) . await ?;
1967
+ let elements = index. get_documents :: < serde_json:: Value > ( ) . await . unwrap ( ) ;
1968
+ assert ! ( matches!( status, Task :: Succeeded { .. } ) ) ;
1969
+ assert ! ( elements. results. len( ) == 2 ) ;
1970
+
1971
+ Ok ( ( ) )
1972
+ }
1973
+
1974
+ #[ meilisearch_test]
1975
+ async fn test_update_documents_ndjson ( client : Client , index : Index ) -> Result < ( ) , Error > {
1976
+ let old_ndjson = r#"{ "id": 1, "body": "doggo" }{ "id": 2, "body": "catto" }"# . as_bytes ( ) ;
1977
+ let updated_ndjson =
1978
+ r#"{ "id": 1, "second_body": "second_doggo" }{ "id": 2, "second_body": "second_catto" }"# . as_bytes ( ) ;
1979
+ // Add first njdson document
1980
+ let task = index
1981
+ . add_documents_ndjson ( old_ndjson, Some ( "id" ) )
1982
+ . await ?
1983
+ . wait_for_completion ( & client, None , None )
1984
+ . await ?;
1985
+ let _ = index. get_task ( task) . await ?;
1986
+
1987
+ // Update via njdson document
1988
+ let task = index
1989
+ . update_documents_ndjson ( updated_ndjson, Some ( "id" ) )
1990
+ . await ?
1991
+ . wait_for_completion ( & client, None , None )
1992
+ . await ?;
1993
+
1994
+ let status = index. get_task ( task) . await ?;
1995
+ let elements = index. get_documents :: < serde_json:: Value > ( ) . await . unwrap ( ) ;
1996
+
1997
+ assert ! ( matches!( status, Task :: Succeeded { .. } ) ) ;
1998
+ assert ! ( elements. results. len( ) == 2 ) ;
1999
+
2000
+ let expected_result = vec ! [
2001
+ json!( { "body" : "doggo" , "id" : 1 , "second_body" : "second_doggo" } ) ,
2002
+ json!( { "body" : "catto" , "id" : 2 , "second_body" : "second_catto" } ) ,
2003
+ ] ;
2004
+
2005
+ assert_eq ! ( elements. results, expected_result) ;
2006
+
2007
+ Ok ( ( ) )
2008
+ }
2009
+
1864
2010
#[ meilisearch_test]
1865
2011
async fn test_get_one_task ( client : Client , index : Index ) -> Result < ( ) , Error > {
1866
2012
let task = index
0 commit comments