I am using elasticsearch-java client (co.elastic.clients) v8.11
I need to create a knn query inside functional_score query similar to query shared below.
{
"size": 3,
"query": {
"function_score": {
"query": {
"knn": {
"field": "embedding",
"query_vector": [2,2,2,0],
"num_candidates": 10,
"_name": "knn_query"
}
},
"functions": [
{
"filter": { "match": { "department": "men" } },
"weight": 100
},
{
"filter": { "match": { "department": "women" } },
"weight": 50
}
]
}
}
}
I have created a KnnQuery object,
KnnQuery knnQuery = new KnnQuery.Builder()
.field("title_vector")
.queryVector(embeddings)
.numCandidates(10)
.similarity(similarityScore)
.boost(getKnnBoost())
.filter(filterQuery._toQuery())
.build();
Now, how can I use it inside my FunctionScoreQuery ?
ltrotta
(Laura Trotta)
August 26, 2024, 2:14pm
2
Hello and welcome! You can add any query to FunctionScoreQuery by using its builder like so:
FunctionScoreQuery.of(fs -> fs
.query(q -> q.knn(your-knn-query))
.functions(list-of-functions));
dadoonet
(David Pilato)
August 26, 2024, 2:20pm
3
Welcome!
I'm not sure it's doable with this version as it has been introduced as a query in 8.12 . Please update to 8.15.0 and you will be probably able to do something like:
client.search(sr -> sr
.index(indexName)
.query(q -> q.functionScore(
fsq -> fsq
.query(qknn -> qknn.knn(
k -> k.field("vector").queryVector(0.9f, 0.4f, 0.8f)
))
.functions(fs -> fs.randomScore(rs -> rs))
))
, Void.class);
I added an example here:
@Test
void kNNWithFunctionScore() throws IOException {
client.indices().create(cir -> cir.index(indexName).mappings(m -> m
.properties("vector", p -> p.denseVector(dv -> dv))
.properties("country", p -> p.keyword(k -> k))
));
client.index(ir -> ir.index(indexName).withJson(new StringReader("{\"country\":\"france\", \"vector\":[1.0, 0.4, 0.8]}")));
client.indices().refresh(rr -> rr.index(indexName));
SearchResponse<Void> response = client.search(sr -> sr
.index(indexName)
.query(q -> q.functionScore(
fsq -> fsq
.query(qknn -> qknn.knn(
k -> k.field("vector").queryVector(0.9f, 0.4f, 0.8f)
))
.functions(fs -> fs.randomScore(rs -> rs.field("country").seed("hello")))
))
, Void.class);
assumeNotNull(response.hits().total());
This file has been truncated. show original
2 Likes