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

[FEATURE] Add knn query support #539

Closed
jhinch opened this issue Jun 24, 2023 · 5 comments
Closed

[FEATURE] Add knn query support #539

jhinch opened this issue Jun 24, 2023 · 5 comments
Labels
enhancement New feature or request

Comments

@jhinch
Copy link

jhinch commented Jun 24, 2023

Is your feature request related to a problem?

Currently it is not possible to construct a query using opensearch-java with a knn query within it using the Query type:

https://opensearch.org/docs/latest/search-plugins/knn/filter-search-knn/#boolean-filter-with-ann-search
https://opensearch.org/docs/latest/search-plugins/knn/filter-search-knn/#lucene-k-nn-filter-implementation

opensearch-java does not contain KnnQuery as a variant it supports and due to the Query.Kind being a enum and the QueryVariant interface requiring a kind being specified it cannot be implemented as a separate library.

What solution would you like?

Given that opensearch-project/k-NN#524 adds precedent for adding KNN functionality into opensearch-java directly and has support for script scoring KNN integration, it seems reasonable that KNN query support be added directly into opensearch-java by adding a KNN variant to the Query.Kind enum and adding KnnQuery and KnnQuery.Builder classes to allow for the construction of these queries.

What alternatives have you considered?

Query.Kind being an enum is restrictive in itself, preventing composability of client library support for non-bundled plugins. It could be that removing this restriction allows for the client to be built separately. But given opensearch-project/k-NN#524 was merged it seems like given if this restriction was removed, it still may be advantageous for consistency to add the KNN query support

Do you have any additional context?

Its not clear whether this request is the exact same thing as #547

@wbeckler
Copy link

Is this not closed by #524 ?

@jhinch
Copy link
Author

jhinch commented Jun 29, 2023

As mentioned in my original description, opensearch-project/k-NN#524 adds the ability to construct an index with a knn_vector field type. It doesn't add the ability to construct a KNN query, only make use of the script score method which doesn't allow for using approximate nearest neighbour searches.

Here are 2 example of a query which is currently unable to be constructed via opensearch-java:

{
  "size": 3,
  "query": {
    "knn": {
      "location": {
        "vector": [5, 4],
        "k": 20
      }
  }
}
{
  "size": 3,
  "query": {
    "knn": {
      "location": {
        "vector": [
          5,
          4
        ],
        "k": 3,
        "filter": {
          "bool": {
            "must": [
              {
                "range": {
                  "rating": {
                    "gte": 8,
                    "lte": 10
                  }
                }
              },
              {
                "term": {
                  "parking": "true"
                }
              }
            ]
          }
        }
      }
    }
  }
}

@dblock
Copy link
Member

dblock commented Jul 5, 2023

@Xtansia @jhinch does #548 cover this?

@Xtansia
Copy link
Collaborator

Xtansia commented Jul 5, 2023

Those queries should now be representable:

        client.search(s -> s
                .index("foobar")
                .size(3)
                .query(q -> q
                        .knn(k -> k
                                .field("location")
                                .vector(new float[] { 5f, 4f })
                                .k(20)
                        )
                ),
                Doc.class
        );

        client.search(s -> s
                .index("foobar")
                .size(3)
                .query(q -> q
                        .knn(k -> k
                                .field("location")
                                .vector(new float[] { 5f, 4f })
                                .k(3)
                                .filter(Query.of(f -> f
                                        .bool(b -> b
                                                .must(m -> m
                                                        .range(r -> r
                                                                .field("rating")
                                                                .gte(JsonData.of(8))
                                                                .lte(JsonData.of(10))
                                                        )
                                                )
                                                .must(m -> m
                                                        .term(t -> t
                                                                .field("parking")
                                                                .value(FieldValue.TRUE)
                                                        )
                                                )
                                        )
                                ))
                                
                        )
                ),
                Doc.class
        );

@jhinch
Copy link
Author

jhinch commented Jul 5, 2023

I had a quick read through and it appears to cover everything in this feature request. I'm happy for this feature request to be closed as fixed

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

5 participants