meilisearch / meilisearch-rust

Rust wrapper for the Meilisearch API.
https://www.meilisearch.com
MIT License
362 stars 90 forks source link

Seeing an error with Request succeeded but failed to parse response Some(ParseError(Error("missing field `updateId`", line: 1, column: 121))) #230

Closed lionkeng closed 2 years ago

lionkeng commented 2 years ago

Description Created a simple rust program that basically runs the example from the documentation.

use futures::executor::block_on;
use meilisearch_sdk::{client::*, document::*};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
struct Movie {
    id: usize,
    title: String,
    genres: Vec<String>,
}

// That trait is required to make a struct usable by an index
impl Document for Movie {
    type UIDType = usize;

    fn get_uid(&self) -> &Self::UIDType {
        &self.id
    }
}

fn main() {
    tracing_subscriber::fmt::init();

    block_on(async move {
        // Create a client (without sending any request so that can't fail)
        let client = Client::new("http://0.0.0.0:7700", "");

        // An index is where the documents are stored.
        let movies = client.index("movies");
        tracing::debug!("movies {:?}", movies);
        // Add some movies in the index. If the index 'movies' does not exist, MeiliSearch creates it when you first add the documents.
        let res = movies
            .add_documents(
                &[
                    Movie {
                        id: 1,
                        title: String::from("Carol"),
                        genres: vec!["Romance".to_string(), "Drama".to_string()],
                    },
                    Movie {
                        id: 2,
                        title: String::from("Wonder Woman"),
                        genres: vec!["Action".to_string(), "Adventure".to_string()],
                    },
                    Movie {
                        id: 3,
                        title: String::from("Life of Pi"),
                        genres: vec!["Adventure".to_string(), "Drama".to_string()],
                    },
                    Movie {
                        id: 4,
                        title: String::from("Mad Max"),
                        genres: vec!["Adventure".to_string(), "Science Fiction".to_string()],
                    },
                    Movie {
                        id: 5,
                        title: String::from("Moana"),
                        genres: vec!["Fantasy".to_string(), "Action".to_string()],
                    },
                    Movie {
                        id: 6,
                        title: String::from("Philadelphia"),
                        genres: vec!["Drama".to_string()],
                    },
                ],
                Some("id"),
            )
            .await;
        if res.is_err() {
            println!("{:?}", res.err());
        }
    })
}

Expected behavior No error when adding document.

Current behavior ERROR meilisearch_sdk::request: Request succeeded but failed to parse response Ran into error Some(ParseError(Error("missing field updateId", line: 1, column: 121)))

Screenshots or Logs If applicable, add screenshots or logs to help explain your problem.

Environment (please complete the following information):

docker run -it --rm \
    -p 7700:7700 \
    -v $(pwd)/data.ms:/data.ms \
    getmeili/meilisearch:latest
irevoire commented 2 years ago

The meilisearch-rust SDK is not compatible with the latest version of meilisearch right now. All the code has been written, though, and a new release should be published in a few hours/days.

If you want to test the code right now you can access it on the bump-meilisearch-v0.25.0 branch

sagar2911 commented 2 years ago

I am using the branch bump-meilisearch-v0.25.0

While using this branch I use a command like : let movies: Index = client.create_index("movies", Some("movie_id")).await.unwrap(); and this throws an error

mismatched types expected struct meilisearch_sdk::indexes::Index, found enum TaskrustcE0308

I think it's supposed to return an Index but ends up returning a task instead.

irevoire commented 2 years ago

Huum no, in the latest update of Meilisearch, the creation and deletion of indexes are now asynchronous so you don’t get an Index anymore when calling create_index. You can do something like that though:

let movies: Index = client
  .create_index("movies", Some("movie_id"))
  .await
  .unwrap()
  .wait_for_completion(&client, None, None)
  .await
  .unwrap()
  .try_make_index(&client)
  .unwrap(); 
sagar2911 commented 2 years ago

This did not work as it was saying try_make_index required 1 argument but got 0, I used something like this instead whcih worked, Thanks :

client.create_index(name_string, Some("object_id")).await.unwrap().wait_for_completion(&client, None, None)
              .await;
let index = client.get_index(name_string).await.unwrap();
moy2010 commented 2 years ago

I'm getting a similar error when adding the settings:

ParseError(Error(\"invalid type: map, expected u64\", line: 0, column: 0))

The code looks like:

let settings = Settings::new()
                      .with_searchable_attributes(["name", "title"])
                      .with_filterable_attributes(["created_at"]);

let _ = my_index
                      .set_settings(&settings)
                      .await.map_err(log_error); // <- Parse error returned here

I'm suspecting that somewhere down the line there's an invalid type cast to u64, but couldn't find any :/.

irevoire commented 2 years ago

This did not work as it was saying try_make_index required 1 argument but got 0

Sorry for the huge delay I totally missed your message! try_make_index is supposed the client as an argument, you can see the documentation here with a little example. And I updated my comment thanks :+1:


@moy2010 I tried to reproduce your issue but I don't know how to do! Could you checkout this branch, then run cargo run --example settings and tell me if it throws any error?

Here you can see the code it'll execute; https://github.com/irevoire/meilisearch-rust/blob/settings-example/examples/settings.rs

moy2010 commented 2 years ago

Hi, @irevoire . I run your example, but it didn't fail. Although, I've narrowed down where the error comes from in my case.

I mistakenly thought that it was coming from when setting the settings, but it's in fact coming when creating the index (client.create_index), specifically when parsing the response body:

fn parse_response<Output: DeserializeOwned>(
    status_code: u16,
    expected_status_code: u16,
    body: String,
) -> Result<Output, Error> {
    if status_code == expected_status_code {
        match from_str::<Output>(&body) {
            Ok(output) => {
                trace!("Request succeed");
                return Ok(output);
            }
            Err(e) => {
                error!("Request succeeded but failed to parse response");
                return Err(Error::ParseError(e));
            }
        };

I can see in the console "Request succeeded but failed to parse response" right before the parse error.

I will ignore the error and add the settings anyway. If I can further reduce the scope of the error, will let you know.