|  | 
|  | 1 | +use crate::{errors::Error, indexes::Index}; | 
|  | 2 | +use serde::{de::DeserializeOwned, Deserialize, Serialize}; | 
|  | 3 | + | 
|  | 4 | +#[derive(Debug, Clone, Deserialize)] | 
|  | 5 | +pub struct DocumentsResults<T> { | 
|  | 6 | +    pub results: Vec<T>, | 
|  | 7 | +    pub limit: u32, | 
|  | 8 | +    pub offset: u32, | 
|  | 9 | +    pub total: u32, | 
|  | 10 | +} | 
|  | 11 | + | 
|  | 12 | +#[derive(Debug, Clone, Serialize)] | 
|  | 13 | +pub struct DocumentsQuery<'a> { | 
|  | 14 | +    #[serde(skip_serializing)] | 
|  | 15 | +    pub index: &'a Index, | 
|  | 16 | + | 
|  | 17 | +    /// The number of documents to skip. | 
|  | 18 | +    /// If the value of the parameter `offset` is `n`, the `n` first documents will not be returned. | 
|  | 19 | +    /// This is helpful for pagination. | 
|  | 20 | +    /// | 
|  | 21 | +    /// Example: If you want to skip the first document, set offset to `1`. | 
|  | 22 | +    #[serde(skip_serializing_if = "Option::is_none")] | 
|  | 23 | +    pub offset: Option<usize>, | 
|  | 24 | + | 
|  | 25 | +    /// The maximum number of documents returned. | 
|  | 26 | +    /// If the value of the parameter `limit` is `n`, there will never be more than `n` documents in the response. | 
|  | 27 | +    /// This is helpful for pagination. | 
|  | 28 | +    /// | 
|  | 29 | +    /// Example: If you don't want to get more than two documents, set limit to `2`. | 
|  | 30 | +    /// Default: `20` | 
|  | 31 | +    #[serde(skip_serializing_if = "Option::is_none")] | 
|  | 32 | +    pub limit: Option<usize>, | 
|  | 33 | + | 
|  | 34 | +    /// The fields that should appear in the documents. By default all of the fields are present. | 
|  | 35 | +    #[serde(skip_serializing_if = "Option::is_none")] | 
|  | 36 | +    pub fields: Option<Vec<&'a str>>, | 
|  | 37 | +} | 
|  | 38 | + | 
|  | 39 | +impl<'a> DocumentsQuery<'a> { | 
|  | 40 | +    pub fn new(index: &Index) -> DocumentsQuery { | 
|  | 41 | +        DocumentsQuery { | 
|  | 42 | +            index, | 
|  | 43 | +            offset: None, | 
|  | 44 | +            limit: None, | 
|  | 45 | +            fields: None, | 
|  | 46 | +        } | 
|  | 47 | +    } | 
|  | 48 | + | 
|  | 49 | +    /// Specify the offset. | 
|  | 50 | +    /// | 
|  | 51 | +    /// # Example | 
|  | 52 | +    /// | 
|  | 53 | +    /// ``` | 
|  | 54 | +    /// # use meilisearch_sdk::{client::*, indexes::*, documents::*}; | 
|  | 55 | +    /// # | 
|  | 56 | +    /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); | 
|  | 57 | +    /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); | 
|  | 58 | +    /// # | 
|  | 59 | +    /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); | 
|  | 60 | +    /// let index = client.index("my_index"); | 
|  | 61 | +    /// | 
|  | 62 | +    /// let mut documents_query = DocumentsQuery::new(&index); | 
|  | 63 | +    /// | 
|  | 64 | +    /// documents_query.with_offset(1); | 
|  | 65 | +    /// ``` | 
|  | 66 | +    pub fn with_offset(&mut self, offset: usize) -> &mut DocumentsQuery<'a> { | 
|  | 67 | +        self.offset = Some(offset); | 
|  | 68 | +        self | 
|  | 69 | +    } | 
|  | 70 | + | 
|  | 71 | +    /// Specify the limit. | 
|  | 72 | +    /// | 
|  | 73 | +    /// # Example | 
|  | 74 | +    /// | 
|  | 75 | +    /// ``` | 
|  | 76 | +    /// # use meilisearch_sdk::{client::*, indexes::*, documents::*}; | 
|  | 77 | +    /// # | 
|  | 78 | +    /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); | 
|  | 79 | +    /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); | 
|  | 80 | +    /// # | 
|  | 81 | +    /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); | 
|  | 82 | +    /// let index = client.index("my_index"); | 
|  | 83 | +    /// | 
|  | 84 | +    /// let mut documents_query = DocumentsQuery::new(&index); | 
|  | 85 | +    /// | 
|  | 86 | +    /// documents_query.with_limit(1); | 
|  | 87 | +    /// ``` | 
|  | 88 | +    pub fn with_limit(&mut self, limit: usize) -> &mut DocumentsQuery<'a> { | 
|  | 89 | +        self.limit = Some(limit); | 
|  | 90 | +        self | 
|  | 91 | +    } | 
|  | 92 | + | 
|  | 93 | +    /// Specify the fields to return in the documents. | 
|  | 94 | +    /// | 
|  | 95 | +    /// # Example | 
|  | 96 | +    /// | 
|  | 97 | +    /// ``` | 
|  | 98 | +    /// # use meilisearch_sdk::{client::*, indexes::*, documents::*}; | 
|  | 99 | +    /// # | 
|  | 100 | +    /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); | 
|  | 101 | +    /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); | 
|  | 102 | +    /// # | 
|  | 103 | +    /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); | 
|  | 104 | +    /// let index = client.index("my_index"); | 
|  | 105 | +    /// | 
|  | 106 | +    /// let mut documents_query = DocumentsQuery::new(&index); | 
|  | 107 | +    /// | 
|  | 108 | +    /// documents_query.with_fields(["title"]); | 
|  | 109 | +    /// ``` | 
|  | 110 | +    pub fn with_fields( | 
|  | 111 | +        &mut self, | 
|  | 112 | +        fields: impl IntoIterator<Item = &'a str>, | 
|  | 113 | +    ) -> &mut DocumentsQuery<'a> { | 
|  | 114 | +        self.fields = Some(fields.into_iter().collect()); | 
|  | 115 | +        self | 
|  | 116 | +    } | 
|  | 117 | + | 
|  | 118 | +    /// Execute the get documents query. | 
|  | 119 | +    /// | 
|  | 120 | +    /// # Example | 
|  | 121 | +    /// | 
|  | 122 | +    /// ``` | 
|  | 123 | +    /// # use meilisearch_sdk::{client::*, indexes::*, documents::*}; | 
|  | 124 | +    /// # use serde::{Deserialize, Serialize}; | 
|  | 125 | +    /// # | 
|  | 126 | +    /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); | 
|  | 127 | +    /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); | 
|  | 128 | +    /// # | 
|  | 129 | +    /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); | 
|  | 130 | +    /// | 
|  | 131 | +    /// # futures::executor::block_on(async move { | 
|  | 132 | +    /// # let index = client.create_index("documents_query_execute", None).await.unwrap().wait_for_completion(&client, None, None).await.unwrap().try_make_index(&client).unwrap(); | 
|  | 133 | +    /// #[derive(Debug, Serialize, Deserialize, PartialEq)] | 
|  | 134 | +    /// struct MyObject { | 
|  | 135 | +    ///     id: Option<usize>, | 
|  | 136 | +    ///     kind: String, | 
|  | 137 | +    /// } | 
|  | 138 | +    /// let index = client.index("documents_query_execute"); | 
|  | 139 | +    /// | 
|  | 140 | +    /// let mut documents_query = DocumentsQuery::new(&index); | 
|  | 141 | +    /// | 
|  | 142 | +    /// documents_query.with_offset(1).execute::<MyObject>().await.unwrap(); | 
|  | 143 | +    /// # }); | 
|  | 144 | +    /// ``` | 
|  | 145 | +    pub async fn execute<T: DeserializeOwned + 'static>( | 
|  | 146 | +        &self, | 
|  | 147 | +    ) -> Result<DocumentsResults<T>, Error> { | 
|  | 148 | +        self.index.get_documents_with::<T>(self).await | 
|  | 149 | +    } | 
|  | 150 | +} | 
|  | 151 | + | 
|  | 152 | +#[cfg(test)] | 
|  | 153 | +mod tests { | 
|  | 154 | +    use super::*; | 
|  | 155 | +    use crate::{client::*, indexes::*}; | 
|  | 156 | +    use meilisearch_test_macro::meilisearch_test; | 
|  | 157 | +    use serde::{Deserialize, Serialize}; | 
|  | 158 | + | 
|  | 159 | +    #[derive(Debug, Serialize, Deserialize, PartialEq)] | 
|  | 160 | +    struct MyObject { | 
|  | 161 | +        id: Option<usize>, | 
|  | 162 | +        kind: String, | 
|  | 163 | +    } | 
|  | 164 | + | 
|  | 165 | +    async fn setup_test_index(client: &Client, index: &Index) -> Result<(), Error> { | 
|  | 166 | +        let t0 = index | 
|  | 167 | +            .add_documents( | 
|  | 168 | +                &[ | 
|  | 169 | +                    MyObject { | 
|  | 170 | +                        id: Some(0), | 
|  | 171 | +                        kind: "text".into(), | 
|  | 172 | +                    }, | 
|  | 173 | +                    MyObject { | 
|  | 174 | +                        id: Some(1), | 
|  | 175 | +                        kind: "text".into(), | 
|  | 176 | +                    }, | 
|  | 177 | +                    MyObject { | 
|  | 178 | +                        id: Some(2), | 
|  | 179 | +                        kind: "title".into(), | 
|  | 180 | +                    }, | 
|  | 181 | +                    MyObject { | 
|  | 182 | +                        id: Some(3), | 
|  | 183 | +                        kind: "title".into(), | 
|  | 184 | +                    }, | 
|  | 185 | +                ], | 
|  | 186 | +                None, | 
|  | 187 | +            ) | 
|  | 188 | +            .await?; | 
|  | 189 | + | 
|  | 190 | +        t0.wait_for_completion(client, None, None).await?; | 
|  | 191 | + | 
|  | 192 | +        Ok(()) | 
|  | 193 | +    } | 
|  | 194 | + | 
|  | 195 | +    #[meilisearch_test] | 
|  | 196 | +    async fn test_get_documents_with_execute(client: Client, index: Index) -> Result<(), Error> { | 
|  | 197 | +        setup_test_index(&client, &index).await?; | 
|  | 198 | +        // let documents = index.get_documents(None, None, None).await.unwrap(); | 
|  | 199 | +        let documents = DocumentsQuery::new(&index) | 
|  | 200 | +            .with_limit(1) | 
|  | 201 | +            .with_offset(1) | 
|  | 202 | +            .with_fields(["kind"]) | 
|  | 203 | +            .execute::<MyObject>() | 
|  | 204 | +            .await | 
|  | 205 | +            .unwrap(); | 
|  | 206 | + | 
|  | 207 | +        assert_eq!(documents.limit, 1); | 
|  | 208 | +        assert_eq!(documents.offset, 1); | 
|  | 209 | +        assert_eq!(documents.results.len(), 1); | 
|  | 210 | + | 
|  | 211 | +        Ok(()) | 
|  | 212 | +    } | 
|  | 213 | +    #[meilisearch_test] | 
|  | 214 | +    async fn test_get_documents_with_only_one_param( | 
|  | 215 | +        client: Client, | 
|  | 216 | +        index: Index, | 
|  | 217 | +    ) -> Result<(), Error> { | 
|  | 218 | +        setup_test_index(&client, &index).await?; | 
|  | 219 | +        // let documents = index.get_documents(None, None, None).await.unwrap(); | 
|  | 220 | +        let documents = DocumentsQuery::new(&index) | 
|  | 221 | +            .with_limit(1) | 
|  | 222 | +            .execute::<MyObject>() | 
|  | 223 | +            .await | 
|  | 224 | +            .unwrap(); | 
|  | 225 | + | 
|  | 226 | +        assert_eq!(documents.limit, 1); | 
|  | 227 | +        assert_eq!(documents.offset, 0); | 
|  | 228 | +        assert_eq!(documents.results.len(), 1); | 
|  | 229 | + | 
|  | 230 | +        Ok(()) | 
|  | 231 | +    } | 
|  | 232 | +} | 
0 commit comments