Skip to content

Commit a8c863f

Browse files
authored
feat(search): change search API result to inline key with values (#387)
1 parent ad6ad42 commit a8c863f

File tree

4 files changed

+52
-32
lines changed

4 files changed

+52
-32
lines changed

python/cocoindex/query.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,16 @@ def internal_handler(self) -> _engine.SimpleSemanticsQueryHandler:
6666
return self._lazy_query_handler()
6767

6868
def search(self, query: str, limit: int, vector_field_name: str | None = None,
69-
similarity_metric: index.VectorSimilarityMetric | None = None) -> tuple[list[QueryResult], SimpleSemanticsQueryInfo]:
69+
similarity_metric: index.VectorSimilarityMetric | None = None
70+
) -> tuple[list[QueryResult], SimpleSemanticsQueryInfo]:
7071
"""
7172
Search the index with the given query, limit, vector field name, and similarity metric.
7273
"""
7374
internal_results, internal_info = self.internal_handler().search(
7475
query, limit, vector_field_name,
7576
similarity_metric.value if similarity_metric is not None else None)
76-
fields = [field['name'] for field in internal_results['fields']]
77-
results = [QueryResult(data=dict(zip(fields, result['data'])), score=result['score']) for result in internal_results['results']]
77+
results = [QueryResult(data=result['data'], score=result['score'])
78+
for result in internal_results]
7879
info = SimpleSemanticsQueryInfo(
7980
similarity_metric=index.VectorSimilarityMetric(internal_info['similarity_metric']),
8081
query_vector=internal_info['query_vector'],

src/ops/interface.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -228,20 +228,44 @@ pub struct VectorMatchQuery {
228228
}
229229

230230
#[derive(Debug, Clone, Serialize)]
231-
pub struct QueryResult {
232-
pub data: Vec<Value>,
231+
pub struct QueryResult<Row = Vec<Value>> {
232+
pub data: Row,
233233
pub score: f64,
234234
}
235235

236236
#[derive(Debug, Clone, Serialize)]
237-
pub struct QueryResults {
237+
pub struct QueryResults<Row = Vec<Value>> {
238238
pub fields: Vec<FieldSchema>,
239-
pub results: Vec<QueryResult>,
239+
pub results: Vec<QueryResult<Row>>,
240240
}
241241

242+
impl TryFrom<QueryResults<Vec<Value>>> for QueryResults<serde_json::Value> {
243+
type Error = anyhow::Error;
244+
245+
fn try_from(values: QueryResults<Vec<Value>>) -> Result<Self, Self::Error> {
246+
let results = values
247+
.results
248+
.into_iter()
249+
.map(|r| {
250+
let data = serde_json::to_value(TypedFieldsValue {
251+
schema: &values.fields,
252+
values_iter: r.data.iter(),
253+
})?;
254+
Ok(QueryResult {
255+
data,
256+
score: r.score,
257+
})
258+
})
259+
.collect::<Result<Vec<_>>>()?;
260+
Ok(QueryResults {
261+
fields: values.fields,
262+
results,
263+
})
264+
}
265+
}
242266
#[derive(Debug, Clone, Serialize)]
243267
pub struct QueryResponse {
244-
pub results: QueryResults,
268+
pub results: QueryResults<serde_json::Value>,
245269
pub info: serde_json::Value,
246270
}
247271

src/py/mod.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::prelude::*;
33
use crate::base::spec::VectorSimilarityMetric;
44
use crate::execution::query;
55
use crate::lib_context::{clear_lib_context, get_auth_registry, init_lib_context};
6-
use crate::ops::interface::QueryResults;
6+
use crate::ops::interface::{QueryResult, QueryResults};
77
use crate::ops::py_factory::PyOpArgSchema;
88
use crate::ops::{interface::ExecutorFactory, py_factory::PyFunctionFactory, register_factory};
99
use crate::server::{self, ServerSettings};
@@ -264,24 +264,24 @@ impl SimpleSemanticsQueryHandler {
264264
vector_field_name: Option<String>,
265265
similarity_metric: Option<Pythonized<VectorSimilarityMetric>>,
266266
) -> PyResult<(
267-
Pythonized<QueryResults>,
267+
Pythonized<Vec<QueryResult<serde_json::Value>>>,
268268
Pythonized<query::SimpleSemanticsQueryInfo>,
269269
)> {
270270
py.allow_threads(|| {
271-
let (results, info) = get_runtime()
272-
.block_on(async move {
273-
self.0
274-
.search(
275-
query,
276-
limit,
277-
vector_field_name,
278-
similarity_metric.map(|m| m.0),
279-
)
280-
.await
281-
})
282-
.into_py_result()?;
283-
Ok((Pythonized(results), Pythonized(info)))
271+
let (results, info) = get_runtime().block_on(async move {
272+
self.0
273+
.search(
274+
query,
275+
limit,
276+
vector_field_name,
277+
similarity_metric.map(|m| m.0),
278+
)
279+
.await
280+
})?;
281+
let results = QueryResults::<serde_json::Value>::try_from(results)?;
282+
anyhow::Ok((Pythonized(results.results), Pythonized(info)))
284283
})
284+
.into_py_result()
285285
}
286286
}
287287

src/service/search.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
1-
use std::sync::Arc;
1+
use crate::prelude::*;
22

33
use axum::extract::Path;
44
use axum::http::StatusCode;
5-
use serde::Deserialize;
65

7-
use axum::{extract::State, Json};
8-
use axum_extra::extract::Query;
9-
10-
use crate::base::spec;
116
use crate::lib_context::LibContext;
127
use crate::ops::interface::QueryResponse;
13-
14-
use super::error::ApiError;
8+
use axum::{extract::State, Json};
9+
use axum_extra::extract::Query;
1510

1611
#[derive(Debug, Deserialize)]
1712
pub struct SearchParams {
@@ -51,7 +46,7 @@ pub async fn search(
5146
.search(query.query, query.limit, query.field, query.metric)
5247
.await?;
5348
let response = QueryResponse {
54-
results,
49+
results: results.try_into()?,
5550
info: serde_json::to_value(info).map_err(|e| {
5651
ApiError::new(
5752
&format!("Failed to serialize query info: {e}"),

0 commit comments

Comments
 (0)