mirror of
https://github.com/meilisearch/meilisearch.git
synced 2025-07-27 08:41:00 +00:00
Template rendering
This commit is contained in:
@ -13,6 +13,7 @@ use meilisearch_types::error::ResponseError;
|
|||||||
use meilisearch_types::error::{Code};
|
use meilisearch_types::error::{Code};
|
||||||
use meilisearch_types::index_uid::IndexUid;
|
use meilisearch_types::index_uid::IndexUid;
|
||||||
use meilisearch_types::keys::actions;
|
use meilisearch_types::keys::actions;
|
||||||
|
use meilisearch_types::milli::vector::json_template::{self, JsonTemplate};
|
||||||
use meilisearch_types::serde_cs::vec::CS;
|
use meilisearch_types::serde_cs::vec::CS;
|
||||||
use meilisearch_types::{heed, milli, Index};
|
use meilisearch_types::{heed, milli, Index};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@ -165,6 +166,8 @@ enum RenderError {
|
|||||||
|
|
||||||
DocumentNotFound(String),
|
DocumentNotFound(String),
|
||||||
BothInlineDocAndDocId,
|
BothInlineDocAndDocId,
|
||||||
|
TemplateParsing(json_template::Error),
|
||||||
|
TemplateRendering(json_template::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<heed::Error> for RenderError {
|
impl From<heed::Error> for RenderError {
|
||||||
@ -282,6 +285,14 @@ impl From<RenderError> for ResponseError {
|
|||||||
String::from("A document id was provided but adding it to the input would overwrite the `doc` field that you already defined inline."),
|
String::from("A document id was provided but adding it to the input would overwrite the `doc` field that you already defined inline."),
|
||||||
Code::InvalidRenderInput,
|
Code::InvalidRenderInput,
|
||||||
),
|
),
|
||||||
|
TemplateParsing(err) => ResponseError::from_msg(
|
||||||
|
format!("Error parsing template: {}", err.parsing_error("input")),
|
||||||
|
Code::InvalidRenderTemplate,
|
||||||
|
),
|
||||||
|
TemplateRendering(err) => ResponseError::from_msg(
|
||||||
|
format!("Error rendering template: {}", err.rendering_error("input")),
|
||||||
|
Code::InvalidRenderTemplate,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -438,7 +449,14 @@ async fn render(index: Index, query: RenderQuery) -> Result<RenderResult, Render
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(RenderResult { template, rendered: String::from("TODO: Implement render logic here") })
|
let json_template = JsonTemplate::new(template.clone())
|
||||||
|
.map_err(TemplateParsing)?;
|
||||||
|
|
||||||
|
let rendered = json_template
|
||||||
|
.render_serializable(&media)
|
||||||
|
.map_err(TemplateRendering)?;
|
||||||
|
|
||||||
|
Ok(RenderResult { template, rendered })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Deserr, ToSchema)]
|
#[derive(Debug, Clone, PartialEq, Deserr, ToSchema)]
|
||||||
@ -471,5 +489,5 @@ pub struct RenderQueryInput {
|
|||||||
#[derive(Debug, Clone, Serialize, PartialEq, ToSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ToSchema)]
|
||||||
pub struct RenderResult {
|
pub struct RenderResult {
|
||||||
template: serde_json::Value,
|
template: serde_json::Value,
|
||||||
rendered: String,
|
rendered: serde_json::Value,
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use liquid::{Parser, Template};
|
use liquid::{Object, Parser, Template};
|
||||||
|
use serde::Serialize;
|
||||||
use serde_json::{Map, Value};
|
use serde_json::{Map, Value};
|
||||||
|
|
||||||
use crate::prompt::ParseableDocument;
|
use crate::prompt::ParseableDocument;
|
||||||
@ -61,21 +62,35 @@ pub struct Error {
|
|||||||
impl Error {
|
impl Error {
|
||||||
/// Produces an error message when the error happened at rendering time.
|
/// Produces an error message when the error happened at rendering time.
|
||||||
pub fn rendering_error(&self, root: &str) -> String {
|
pub fn rendering_error(&self, root: &str) -> String {
|
||||||
|
if self.path.is_empty() {
|
||||||
|
format!(
|
||||||
|
"error while rendering template: {}",
|
||||||
|
&self.template_error
|
||||||
|
)
|
||||||
|
} else {
|
||||||
format!(
|
format!(
|
||||||
"in `{}`, error while rendering template: {}",
|
"in `{}`, error while rendering template: {}",
|
||||||
path_with_root(root, self.path.iter()),
|
path_with_root(root, self.path.iter()),
|
||||||
&self.template_error
|
&self.template_error
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Produces an error message when the error happened at parsing time.
|
/// Produces an error message when the error happened at parsing time.
|
||||||
pub fn parsing(&self, root: &str) -> String {
|
pub fn parsing_error(&self, root: &str) -> String {
|
||||||
|
if self.path.is_empty() {
|
||||||
|
format!(
|
||||||
|
"error while parsing template: {}",
|
||||||
|
&self.template_error
|
||||||
|
)
|
||||||
|
} else {
|
||||||
format!(
|
format!(
|
||||||
"in `{}`, error while parsing template: {}",
|
"in `{}`, error while parsing template: {}",
|
||||||
path_with_root(root, self.path.iter()),
|
path_with_root(root, self.path.iter()),
|
||||||
&self.template_error
|
&self.template_error
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JsonTemplate {
|
impl JsonTemplate {
|
||||||
@ -134,6 +149,17 @@ impl JsonTemplate {
|
|||||||
self.render(&search_data)
|
self.render(&search_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Renders any serializable value by converting it to a liquid object and rendering it with the template.
|
||||||
|
/// If its a map, values inside can be accessed directly by their keys.
|
||||||
|
pub fn render_serializable<T: Serialize>(&self, object: &T) -> Result<Value, Error> {
|
||||||
|
let object = liquid::to_object(object)
|
||||||
|
.map_err(|err| Error {
|
||||||
|
template_error: err,
|
||||||
|
path: ValuePath::new(),
|
||||||
|
})?;
|
||||||
|
self.render(&object)
|
||||||
|
}
|
||||||
|
|
||||||
/// The JSON value representing the underlying template
|
/// The JSON value representing the underlying template
|
||||||
pub fn template(&self) -> &Value {
|
pub fn template(&self) -> &Value {
|
||||||
&self.value
|
&self.value
|
||||||
|
@ -113,7 +113,7 @@ impl RequestData {
|
|||||||
for (name, value) in indexing_fragments {
|
for (name, value) in indexing_fragments {
|
||||||
JsonTemplate::new(value).map_err(|error| {
|
JsonTemplate::new(value).map_err(|error| {
|
||||||
NewEmbedderError::rest_could_not_parse_template(
|
NewEmbedderError::rest_could_not_parse_template(
|
||||||
error.parsing(&format!(".indexingFragments.{name}")),
|
error.parsing_error(&format!(".indexingFragments.{name}")),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
@ -623,7 +623,7 @@ impl RequestFromFragments {
|
|||||||
.map(|(name, value)| {
|
.map(|(name, value)| {
|
||||||
let json_template = JsonTemplate::new(value).map_err(|error| {
|
let json_template = JsonTemplate::new(value).map_err(|error| {
|
||||||
NewEmbedderError::rest_could_not_parse_template(
|
NewEmbedderError::rest_could_not_parse_template(
|
||||||
error.parsing(&format!(".searchFragments.{name}")),
|
error.parsing_error(&format!(".searchFragments.{name}")),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok((name, json_template))
|
Ok((name, json_template))
|
||||||
|
Reference in New Issue
Block a user