Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SearchResults<T> doesn't implement trait serde::Serialize #517

Open
ZelCloud opened this issue Sep 9, 2023 · 5 comments
Open

SearchResults<T> doesn't implement trait serde::Serialize #517

ZelCloud opened this issue Sep 9, 2023 · 5 comments
Labels
enhancement New feature or request

Comments

@ZelCloud
Copy link

ZelCloud commented Sep 9, 2023

Description
Not sure if this is a bug or a feature request.

SearchResults doesn't seem to have the serde serialize trait, this prevents passing the results to something like actix httpresponse json.

code block

#[macro_use]
extern crate diesel;

extern crate env_logger;

use std::env;

use actix_cors::Cors;
use actix_web::{
    delete, get, middleware, patch, post,
    web::{self, Data},
    App, HttpRequest, HttpResponse, HttpServer,
};

use serde::{Deserialize, Serialize};
use serde_json::Result;

use chrono::{DateTime, Utc};

use meilisearch_sdk::client::*;

#[derive(Debug, Serialize, Deserialize)]
pub struct Posting {
    pub id: uuid::Uuid,
    pub title: String,
    pub link: String,
    pub rating: i32,
    pub summary: Option<String>,
    pub updated_at: DateTime<Utc>,
    pub created_at: DateTime<Utc>,
}

#[get("/search-test")]
async fn get_r_search_test(
    req: HttpRequest,
    meili_client: web::Data<meilisearch_sdk::client::Client>,
) -> Result<HttpResponse> {
    let results = meili_client
        .index("movies")
        .search()
        .with_query("Apple")
        .execute::<crate::models::Posting>()
        .await
        .unwrap();

    println!("{:?}", results);

	// ERROR LINE
    Ok(HttpResponse::Ok().json(results))
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    dotenvy::dotenv().ok();

    let meilisearch_url = env::var("MEILISEARCH_URL").expect("Meilisearch URL env not found");
    let meilisearch_master_key = env::var("MEILISEARCH_MASTER_KEY").expect("Meilisearch master API key env not found");
    let meilisearch_client = Client::new(&meilisearch_url, Some(meilisearch_master_key));

    std::env::set_var("RUST_LOG", "actix_web=info");
    env_logger::init();

    HttpServer::new(move || {
        App::new()
            .app_data(Data::new(meilisearch_client.clone()))
            .wrap(middleware::Logger::default())
            .wrap(Cors::permissive())
            .service(web::scope("/api/v1").service(get_r_search_test))
    })
    .bind("127.0.0.1:9004")?
    .run()
    .await
}

Expected behavior
SearchResults will have the serde serialize trait.

Current behavior
HttpResponse::Ok().json(results)
---- ^^^^^^^ the trait _::_serde::Serialize is not implemented for SearchResults<Posting>

Screenshots or Logs
N/A

Environment (please complete the following information):

  • OS: Windows 10 x64
  • Meilisearch version: 1.3.3
  • meilisearch-rust version: 0.24.1
@moy2010
Copy link
Contributor

moy2010 commented Sep 13, 2023

This is not a bug. When you search with Meilisearch's client it will return the SearchResults wrapper around whatever document model you are using for your documents (in this case, you are using crate::models::Posting).

SearchResults is just the response object with the details for the search result (i.e. how many hits or results were returned, in what page you are in case that you are using pagination, etc.) and it's obviously not meant to be exposed to the user, hence why I guess it doesn't implement Serialize. It's the API telling you that you are doing something wrong.

In your case, I would just extract the hits from it and send the response to the consumer of the /search-test endpoint.

@bidoubiwa bidoubiwa added the enhancement New feature or request label Sep 25, 2023
@taufik-nurhidayat
Copy link

What is the solutions for this case?

@CommanderStorm
Copy link

CommanderStorm commented May 17, 2024

What is the solutions for this case?

The solution is entirely dependent on what you WANT the API to return.

Example:

  • do you want the formatted or unformatted result?
  • do you want where the search matches
  • do you want to expose other statistics (facets, paging, ...)?

I would say that adding your own struct for these return types is better.
Rationale: You will get notified earlier (via compilation errors) of any changes you will need to migrate around.

@Tails
Copy link

Tails commented Jun 3, 2024

Running into the same thing, trying to return the query result as Json in a Rocket server. I also had expected the result structs to implement Serialize when T supports it, since the data in the results is pretty harmless to be exposed to the client.

@WillKirkmanM
Copy link

Here's a workaround for now, by defining a new struct that mirrors the search results, then mapping SearchResult to a Vector of Combined Items and then finally construct a serializable structure.

(CombinedItem is my data structure, similar to the author's Posting)
Using Actix:

#[derive(Serialize)]
struct SerializableSearchResults {
    hits: Vec<CombinedItem>,
}

#[get("/search")]
pub async fn search(query: web::Query<SearchQuery>) -> HttpResponse {
    let client = Client::new("http://localhost:7700", None::<&str>).unwrap();
    let index = client.index("library");

    let search_results: SearchResults<CombinedItem> = index.search()
        .with_query(&query.query)
        .execute()
        .await
        .unwrap();

    let hits: Vec<CombinedItem> = search_results.hits.into_iter().map(|result| result.result).collect();

    let serializable_results = SerializableSearchResults {
        hits,
    };

    HttpResponse::Ok().json(serializable_results)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

7 participants